* util/sparc64/ieee1275/misc.c: New file.

* util/sparc64/ieee1275/grub-setup.c: New file.
	* util/sparc64/ieee1275/grub-ofpathname.c: New file.
	* util/sparc64/ieee1275/grub-mkimage.c: New file.
	* util/sparc64/ieee1275/grub-install.in: New file.
	* util/ieee1275/ofpath.c: New file.
	* util/ieee1275/devicemap.c: New file.
	* util/devicemap.c: New file.
	* util/deviceiter.c: New file.
	* kern/sparc64/ieee1275/init.c: New file.
	* include/grub/util/ofpath.h: New file.
	* include/grub/util/deviceiter.h: New file.
	* util/grub-mkdevicemap.c: Include deviceiter.h.
	Implement using grub_util_emit_devicemap_entry and
	grub_util_iterate_devices.
	* conf/i386-corebook.rmk: Build util/deviceiter.c and
	util/devicemap.c into grub-mkdevicemap
	* conf/i386-efi.rmk: Likewise.
	* conf/i386-ieee1275.rmk: Likewise.
	* conf/i386-pc.rmk: Likewise.
	* conf/powerpc-ieee1275.rmk: Likewise.
	* conf/sparc64-ieee1275.rmk: Add rules to build boot block
	images and installation utilities.  Build kernel as image
	instead of as elf binary.  Use common rules as much as possible.
This commit is contained in:
davem 2009-04-22 09:57:39 +00:00
parent 4e8269dad2
commit a1447506fe
20 changed files with 2689 additions and 817 deletions

415
util/ieee1275/ofpath.c Normal file
View file

@ -0,0 +1,415 @@
/* ofpath.c - calculate OpenFirmware path names given an OS device */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#undef OFPATH_STANDALONE
#ifndef OFPATH_STANDALONE
#include <grub/types.h>
#include <grub/util/misc.h>
#include <grub/util/ofpath.h>
#endif
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#ifdef OFPATH_STANDALONE
#define UNUSED __attribute__((unused))
#define xmalloc malloc
void
grub_util_error (const char *fmt, ...)
{
va_list ap;
fprintf (stderr, "ofpath: error: ");
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
fputc ('\n', stderr);
exit (1);
}
#endif
static void
kill_trailing_dir(char *path)
{
char *end = path + strlen(path) - 1;
while (end >= path)
{
if (*end != '/')
{
end--;
continue;
}
*end = '\0';
break;
}
}
static void
trim_newline (char *path)
{
char *end = path + strlen(path) - 1;
while (*end == '\n')
*end-- = '\0';
}
#define OF_PATH_MAX 256
static void
find_obppath(char *of_path, const char *sysfs_path_orig)
{
char *sysfs_path, *path;
sysfs_path = xmalloc (PATH_MAX);
path = xmalloc (PATH_MAX);
strcpy(sysfs_path, sysfs_path_orig);
while (1)
{
int fd;
snprintf(path, PATH_MAX, "%s/obppath", sysfs_path);
#if 0
printf("Trying %s\n", path);
#endif
fd = open(path, O_RDONLY);
if (fd < 0)
{
kill_trailing_dir(sysfs_path);
if (!strcmp(sysfs_path, "/sys"))
grub_util_error("'obppath' not found in parent dirs of %s",
sysfs_path_orig);
continue;
}
memset(of_path, 0, OF_PATH_MAX);
read(fd, of_path, OF_PATH_MAX);
close(fd);
trim_newline(of_path);
break;
}
free (path);
free (sysfs_path);
}
static void
block_device_get_sysfs_path_and_link(const char *devicenode,
char *sysfs_path, int sysfs_path_len)
{
char *rpath = xmalloc (PATH_MAX);
snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode);
if (!realpath (sysfs_path, rpath))
grub_util_error ("Cannot get the real path of `%s'", sysfs_path);
strcat(rpath, "/device");
if (!realpath (rpath, sysfs_path))
grub_util_error ("Cannot get the real path of `%s'", rpath);
free (rpath);
}
static const char *
trailing_digits (const char *p)
{
const char *end;
end = p + strlen(p) - 1;
while (end >= p)
{
if (! isdigit(*end))
break;
end--;
}
return end + 1;
}
static void
__of_path_common(char *of_path, char *sysfs_path,
const char *device, int devno)
{
const char *digit_string;
char disk[64];
find_obppath(of_path, sysfs_path);
digit_string = trailing_digits (device);
if (*digit_string == '\0')
{
sprintf(disk, "/disk@%d", devno);
}
else
{
int part;
sscanf(digit_string, "%d", &part);
sprintf(disk, "/disk@%d:%c", devno, 'a' + (part - 1));
}
strcat(of_path, disk);
}
static char *
get_basename(char *p)
{
char *ret = p;
while (*p)
{
if (*p == '/')
ret = p + 1;
p++;
}
return ret;
}
static void
of_path_of_vdisk(char *of_path,
const char *devname UNUSED, const char *device,
const char *devnode UNUSED, const char *devicenode)
{
char *sysfs_path, *p;
int devno, junk;
sysfs_path = xmalloc (PATH_MAX);
block_device_get_sysfs_path_and_link(devicenode,
sysfs_path, PATH_MAX);
p = get_basename (sysfs_path);
sscanf(p, "vdc-port-%d-%d", &devno, &junk);
__of_path_common(of_path, sysfs_path, device, devno);
free (sysfs_path);
}
static void
of_path_of_ide(char *of_path,
const char *devname UNUSED, const char *device,
const char *devnode UNUSED, const char *devicenode)
{
char *sysfs_path, *p;
int chan, devno;
sysfs_path = xmalloc (PATH_MAX);
block_device_get_sysfs_path_and_link(devicenode,
sysfs_path, PATH_MAX);
p = get_basename (sysfs_path);
sscanf(p, "%d.%d", &chan, &devno);
__of_path_common(of_path, sysfs_path, device, devno);
free (sysfs_path);
}
static int
vendor_is_ATA(const char *path)
{
int fd, err;
char *buf;
buf = xmalloc (PATH_MAX);
snprintf(buf, PATH_MAX, "%s/vendor", path);
fd = open(buf, O_RDONLY);
if (fd < 0)
grub_util_error ("Cannot open 'vendor' node of `%s'", path);
memset(buf, 0, PATH_MAX);
err = read(fd, buf, PATH_MAX);
if (err < 0)
grub_util_error ("Cannot read 'vendor' node of `%s'", path);
close(fd);
free (buf);
if (!strncmp(buf, "ATA", 3))
return 1;
return 0;
}
static void
check_sas (char *sysfs_path, int *tgt)
{
char *ed = strstr (sysfs_path, "end_device");
char *p, *q, *path;
char phy[16];
int fd;
if (!ed)
return;
/* SAS devices are identified using disk@$PHY_ID */
p = strdup (sysfs_path);
ed = strstr(p, "end_device");
q = ed;
while (*q && *q != '/')
q++;
*q = '\0';
path = xmalloc (PATH_MAX);
sprintf (path, "%s/sas_device:%s/phy_identifier", p, ed);
fd = open(path, O_RDONLY);
if (fd < 0)
grub_util_error("Cannot open SAS PHY ID '%s'\n", path);
memset (phy, 0, sizeof (phy));
read (fd, phy, sizeof (phy));
sscanf (phy, "%d", tgt);
free (path);
free (p);
}
static void
of_path_of_scsi(char *of_path,
const char *devname UNUSED, const char *device,
const char *devnode UNUSED, const char *devicenode)
{
const char *p, *digit_string, *disk_name;
int host, bus, tgt, lun;
char *sysfs_path, disk[64];
sysfs_path = xmalloc (PATH_MAX);
block_device_get_sysfs_path_and_link(devicenode,
sysfs_path, PATH_MAX);
p = get_basename (sysfs_path);
sscanf(p, "%d:%d:%d:%d", &host, &bus, &tgt, &lun);
check_sas (sysfs_path, &tgt);
if (vendor_is_ATA(sysfs_path))
{
__of_path_common(of_path, sysfs_path, device, tgt);
free (sysfs_path);
return;
}
find_obppath(of_path, sysfs_path);
free (sysfs_path);
if (strstr (of_path, "qlc"))
strcat (of_path, "/fp@0,0");
if (strstr (of_path, "sbus"))
disk_name = "sd";
else
disk_name = "disk";
digit_string = trailing_digits (device);
if (*digit_string == '\0')
{
sprintf(disk, "/%s@%x,%d", disk_name, tgt, lun);
}
else
{
int part;
sscanf(digit_string, "%d", &part);
sprintf(disk, "/%s@%x,%d:%c", disk_name, tgt, lun, 'a' + (part - 1));
}
strcat(of_path, disk);
}
static char *
strip_trailing_digits (const char *p)
{
char *new, *end;
new = strdup (p);
end = new + strlen(new) - 1;
while (end >= new)
{
if (! isdigit(*end))
break;
*end-- = '\0';
}
return new;
}
char *
grub_util_devname_to_ofpath (char *devname)
{
char *name_buf, *device, *devnode, *devicenode, *ofpath;
name_buf = xmalloc (PATH_MAX);
name_buf = realpath (devname, name_buf);
if (! name_buf)
grub_util_error ("Cannot get the real path of `%s'", devname);
device = get_basename (devname);
devnode = strip_trailing_digits (devname);
devicenode = strip_trailing_digits (device);
ofpath = xmalloc (OF_PATH_MAX);
if (device[0] == 'h' && device[1] == 'd')
of_path_of_ide(ofpath, name_buf, device, devnode, devicenode);
else if (device[0] == 's'
&& (device[1] == 'd' || device[1] == 'r'))
of_path_of_scsi(ofpath, name_buf, device, devnode, devicenode);
else if (device[0] == 'v' && device[1] == 'd' && device[2] == 'i'
&& device[3] == 's' && device[4] == 'k')
of_path_of_vdisk(ofpath, name_buf, device, devnode, devicenode);
free (devnode);
free (devicenode);
free (name_buf);
return ofpath;
}
#ifdef OFPATH_STANDALONE
int main(int argc, char **argv)
{
char *of_path;
if (argc != 2)
{
printf("Usage: grub-ofpathname DEVICE\n");
return 1;
}
of_path = grub_util_devname_to_ofpath (argv[1]);
printf("%s\n", of_path);
return 0;
}
#endif