All of lore.kernel.org
 help / color / mirror / Atom feed
* [PPC] quick test please? device tree path translation
@ 2005-10-23 22:53 Hollis Blanchard
  2005-10-24  0:19 ` Mike Small
  0 siblings, 1 reply; 6+ messages in thread
From: Hollis Blanchard @ 2005-10-23 22:53 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 842 bytes --]

Hi, could PPC people give the attached shell script a try? For example,
$ ./ofpathname /dev/hda
/pci@80000000/pci-bridge@d/pci-ata@1/@0/disk@0

I'd like to make sure that the resulting Open Firmware device tree path 
is accurate. I think we should use this script for GRUB installation, 
which means that when the user says "grub-install /dev/hda2" this 
script will tell us the proper setting of the OF "boot-device" 
variable.

It seems to be working fine for disk, CD, and Zip drive on my Blue & 
White G3, which has a slightly unusual ATA setup. I expect it to work 
just fine on simple systems like laptops, but I'm particularly 
interested in more unsual systems like Pegasos, or systems with lots of 
IO and disks.

You can validate by comparing the output with 
/proc/device-tree/aliases/hd, for example, or just try it out.

-Hollis

[-- Attachment #2: ofpathname --]
[-- Type: application/octet-stream, Size: 12452 bytes --]

#! /bin/bash
# Copyright (c) 2004 International Business Machines
# Common Public License Version 1.0 (see COPYRIGHT)

#
# ofpathname - This utility provides a machanism for converting a logical
# device name to an open firmware device path, and vice versa.
#
# TODO: This script doesn't handle floppy drives and token ring devices,
#       perhaps they should be added in at some point.
#

OFPATHNAME="ofpathname"
VERSION="0.4"
FIND=/usr/bin/find
CAT=/bin/cat

# Usage statemnet
usage()
{
    echo "Usage: $OFPATHNAME [OPTION] DEVICE"
    echo "Report the Open Firmware device pathname for logical device DEVICE"
    echo ""
    echo "Optional arguments."
    echo "  -l               Convert Open Firmware device pathname to"
    echo "                   logical device name."
    echo "  -q, --quiet      do not report failures, exit quietly"
    echo "  -V, --version    display version information and exit"         
    echo "  -h, --help       display this help information and exit"
    echo ""
}

show_version()
{
    echo "$OFPATHNAME: Version $VERSION"
    echo "Written by: Nathan Fontenot"
}

# 
# err
# Common routine to print error messages for ofpathname.  Since most of the
# error messages can be generated in multiple places, we put all the text
# here to avoid errors in duplicating the messages.
#
# The first and only parameteris the error message number, all of which
# are defined below as ERR_*.
#
ERR_NO_OFPATH=1
ERR_NO_SYSFS=2
ERR_NO_SYSFS_DEVINFO=3
ERR_NOT_CONFIG=4
ERR_NO_LOGDEV=5
err()
{
    local emsg=$1
    if [[ -z $be_quiet ]]; then	
	case $emsg in
	    1)	echo "$OFPATHNAME: Could not retrieve Open Firmware device path"
	        echo "            for logical device \"$DEVNAME_ARG\"." ;;
	    
	    2)  echo "$OFPATHNAME: sysfs (/sys) is needed and does not appear"
		echo "            to be mounted on this system." ;;
	    
	    3)  echo "$OFPATHNAME: Could not find sysfs information for logical"
		echo "            device \"$DEVNAME_ARG\"." ;;
	    
	    4)  echo "$OFPATHANME: Logical device \"$DEVNAME_ARG\" does not appear"
		echo "            to be configured." ;;

	    5)  echo "$OFPATHNAME: Could not retrieve logical device name for"
		echo "            Open Firmware path \"$DEVNAME_ARG\"."
	esac
    fi

    exit 1
}

#
# get_link
# return the directory path that a link points to.
# The only parameter is the link name.
#
get_link()
{
    echo `ls -l $ln_name 2>/dev/null | awk -F"->" '{print $2}'`
}

#
# get_hbtl
# Given a path that ends in an HBTL (Host:Bus:Target:LUN), break it apart
# into its constituent parts in the global vars HOST, BUS, TARGET and LUN
#
# #1 path ending in HBTL
#
get_hbtl()
{
    local hbtl

    HBTL=${1##*/}
    hbtl=$HBTL

    HOST=${hbtl%%:*}
    hbtl=${hbtl#*:}
    BUS=${hbtl%%:*}
    hbtl=${hbtl#*:}
    TARGET=${hbtl%%:*}
    LUN=${hbtl#*:}
}

#
# get_vdisk_no
# Given a path that ends in an HBTL, convert the HBTL values into a 
# virtual disk number (not sure what the real terminology is for it).
# To do the conversion, the HBTL (A:B:C:D) is split apart and 
# calculated as;
#     no = (0x8000000000000000 | B << 8 | C << 5 | D)
# 
# $1 path ending in HBTL
#
get_vdisk_no()
{
    get_hbtl $1

    local B C D
    typeset -i B C D

    B=$((0x$BUS << 8))
    C=$((0x$TARGET << 5))
    D=$((0x$LUN))

    local vdiskno vdisk
    typeset -i vdiskno
    vdiskno=$((0x8000000000000000 | $B | $C | $D ))
    vdisk=${vdiskno##-}

    echo `bc << END
ibase=10
obase=16
$vdisk
END`
}

#
# get_scsi_host
# Construct the scsi@XXX part of a Open Firmware device path from a
# given device directory
# 
# $1 - device 
#
get_scsi_host()
{
    local device_dir=$1
    local dir
    local scsi_name
    
    # build the scsi name 
    cd /sys/class/scsi_host
    for dir in `$FIND . -name $device_dir -follow`; do
        goto_dir $dir "unique_id"
        scsi_name=`$CAT "unique_id"`
	echo scsi@$scsi_name
        break
    done
}

#
# goto_dir
# This looks for a given file in a given directory or any parents of the 
# given directory.
#
# $1 starting directory
# $2 file to search for
#  
goto_dir()
{
    local start_dir=$1
    local fname=$2
    local found=0

    cd $start_dir
    while [[ $PWD != "/" ]]; do
	ls 2>/dev/null | grep $fname >/dev/null 2>&1
	if [[ $? -eq 0 ]]; then
	    found=1
	    break
	fi
	cd ..
    done

    if [[ $found -eq 0 ]]; then
	err $ERR_NO_SYSFS_DEVINFO
    fi
}

#
# logical_to_ofpathname
# Conversion for logical device name to an Open Firmware device path
#
logical_to_ofpathname()
{
    local is_cdrom

    # follow any links to the real device name
    while [[ -L $DEVNAME ]]; do
        DEVNAME=`get_link $DEVNAME`
    done
    while [[ -L /dev/$DEVNAME ]]; do
        DEVNAME=`get_link /dev/$DEVNAME`
    done

    DEVICE=${DEVNAME##*/}
    DEVNODE=${DEVICE%%[0-9]*}

    # try to determine if this is a cdrom device
    if [[ ${DEVNAME_ARG##*/} = cdrom ]]; then
	is_cdrom=yes
    elif [[ `get_link /dev/cdrom` = /dev/$DEVICE ]]; then
	is_cdrom=yes
    else
	is_cdrom=no
    fi

    case $DEVICE in
	eth*)	    l2of_ethernet ;;
    	sd* | sr*)  l2of_scsi ;;
	hd*)        l2of_ide ;;
	fd*)	    echo "no fd support yet" ;;
    esac

    if [[ -z $OF_PATH ]]; then
        err $ERR_NO_OFPATH
    fi

    if [[ $is_cdrom = yes ]]; then
	OF_PATH=$OFPATH:1\\ppc\\bootinfo.txt
    fi

    echo $OF_PATH
}

#
# l2of_ide
# Conversion routine for logical => OF path of ide devices
#
l2of_ide()
{
    cd /sys/block/$DEVICE
    local link=`get_link "device"`
    if [[ -z $link ]]; then 
	err $ERR_NO_SYSFS_DEVINFO
    fi
    cd $link

    # get the device number
    local devdir=${PWD##/*/}
    local channelno=${devdir%%\.*}
    local devno=${devdir##*\.}

    goto_dir $PWD "devspec"

    OF_PATH=`$CAT $PWD/devspec`
    if [[ -z $OF_PATH ]]; then
        err $ERR_NO_OFPATH
    fi

    # PCI ATA controller nodes (found on some Macs) have one child node per IDE
    # channel.
    case `$CAT "/proc/device-tree/$OF_PATH/device_type"` in
    pci-ata|pci-ide) OF_PATH=$OF_PATH/@$channelno ;;
    esac

    OF_PATH=$OF_PATH/disk@$devno
}

#
# l2of_ethernet
# Conversion routine for logical => OF path of ethernet devices
#
l2of_ethernet()
{
    local sysfs_eth=`$FIND /sys -name $DEVICE 2> /dev/null`
    if [[ -z $sysfs_eth ]]; then
	err $ERR_NOT_CONFIG
    fi

    OF_PATH=`$CAT $sysfs_eth/device/devspec`
    if [[ -z $OF_PATH ]]; then
	err $ERR_NO_OFPATH
    fi
}

#
# l2of_scsi
# Converion routine for logical => OF path of scsi devices
#
l2of_scsi()
{
    local sysfs_sd=`$FIND /sys -name $DEVICE 2>/dev/null`
    if [[ -z $sysfs_sd ]]; then
	err $ERR_NOT_CONFIG
    fi

    # Move up directories until we find onew with a device link
    goto_dir $sysfs_sd "device"

    # follow the 'device' link
    local link=`get_link "device"`
    if [[ -z $link ]]; then 
	err $ERR_NO_SYSFS_DEVINFO
    fi

    get_hbtl $link 
    cd $link

    # save the name of the current directory, we may need it later...
    local device_dir=${PWD##/*/}

    # move up directories until we find one with devspec information
    goto_dir $PWD "devspec"

    OF_PATH=`$CAT $PWD/devspec`
    if [[ -z $OF_PATH ]]; then
        err $ERR_NO_OFPATH
    fi

    local vdev=${OF_PATH%/*}

    if [[ $vdev = "/vdevice" ]]; then
	# get the v-device data
	local i vdiskno
	cd host*
	for i in *:*:*:*; do
	    vdiskno=`get_vdisk_no $i`
	done

	OF_PATH=$OF_PATH/disk\@$vdiskno

    else
        # make sure the "scsi" information is on the end of the path
        local scsi_name=${OF_PATH##/*/}
        scsi_name=${scsi_name%%@*}
        if [[ $scsi_name != "scsi" ]]; then
	    scsi_name=`get_scsi_host $device_dir`
	    OF_PATH=$OF_PATH/$scsi_name
        fi

        OF_PATH=$OF_PATH/sd@$TARGET,$LUN
    fi

}

#
# ofpathname_to_logical
# Conversion for Open Firmware device paths to logical device names
#
ofpathname_to_logical()
{
    DEVPATH=${DEVNAME%/*}
    DEVICE=${DEVNAME##/*/}
    DEVTYPE=${DEVICE%\@*}

    # Remove any possible cdrom data from DEVICE
    if [[ ${DEVICE##*,} = "\ppc\bootinfo.txt" ||
	  ${DEVICE##*,} = \ppc\bootinfo.txt ]]; then
        DEVICE=${DEVICE%,*}
    fi

    case $DEVTYPE in
	sd*           )  of2l_scsi ;;
	v-scsi | disk )  of2l_vscsi 
			 if [[ -z $LOGICAL_DEVNAME && $DEVTYPE = disk ]]; then
			     of2l_ide
			 fi ;;
        eth* | l-lan  )  of2l_ethernet ;;
	disk*         )  of2l_ide ;;
    esac

    if [[ -z $LOGICAL_DEVNAME ]]; then
        err $ERR_NO_LOGDEV
    fi

    # See if this device is the cdrom
    if [[ `get_link "/dev/cdrom"` = $LOGICAL_DEVNAME ]]; then
	LOGICAL_DEVNAME="cdrom"
    fi

    echo $LOGICAL_DEVNAME
}

#
# of2l_ide
# Conversion routine for OF path => logical name for ide devices
#
of2l_ide()
{
    local dir

    for dir in `$FIND /sys/block -name hd*`; do
	# get devno
	local devno=${DEVICE##*@}
	devno=${devno%%:*}

	cd $dir
	local link=`get_link "device"`
        if [[ -n $link ]]; then 
	    cd $link

	    # see if this is the correct device
	    local this_devno=${PWD##*\.}
	    if [[ $devno -eq $this_devno ]]; then
	        goto_dir $PWD "devspec"
	        local devspec=`$CAT ./devspec 2>/dev/null`
	        if [[ $devspec = $DEVPATH ]]; then
		    LOGICAL_DEVNAME="${dir##*/}"
		    break
	        fi
	    fi
	fi
    done
}

#
# of2l_ethernet
# Conversion routine for OF path => logical names of ethernet devices
#
of2l_ethernet()
{
    local dir

    # strip off ip info if present
    local devname=${DEVNAME%%:*}

    for dir in `$FIND /sys/class/net -name eth*`; do
	goto_dir $dir device

	local link=`get_link "device"`
        if [[ -z $link ]]; then 
	    err $ERR_NO_SYSFS_DEVINFO
        fi

	cd $link
	local devspec=`$CAT ./devspec 2>/dev/null`
	if [[ $devspec = $devname ]]; then
	    LOGICAL_DEVNAME="${dir##*/}"
	    return
	fi
    done
}

#
# of2l_vscsi
# Conversion routine for OF path => logical names of virtual scsi devices
#
of2l_vscsi()
{
    DEV_HBTL_NO=${DEVICE##*\@}

    local dir
    for dir in `$FIND /sys/block -name "s[dr]*"`; do
	# go up to find directory with 'device' link
	goto_dir $dir "device"

	local link=`get_link "device"`	
        if [[ -z $link ]]; then 
	    err $ERR_NO_SYSFS_DEVINFO
        fi

	local vdiskno=`get_vdisk_no $link`

	cd $link	
	if [[ $vdiskno = $DEV_HBTL_NO ]]; then
	    goto_dir $PWD "devspec"
	    local devspec=`$CAT ./devspec 2>/dev/null`
	    if [[ $devspec = $DEVPATH ]]; then
		LOGICAL_DEVNAME=${dir##/*/}
		return
	    fi
	fi
    done


}
	
#
# of2l_scsi
# Conversion routine for OF path => logical names of scsi devices
#
of2l_scsi()
{
    DEV_TARGET=${DEVICE##*\@}
    DEV_TARGET=${DEV_TARGET%%,*}
    DEV_LUN=${DEVICE##*,}

    # At this point DEV_LUN may be in the form X:Y, we're only interested
    # in the X component.         
    DEV_LUN=${DEV_LUN%%:*}

    local dir
    for dir in `$FIND /sys/block -name s[dr]*`; do
	# go up to find directory with 'device' link
	goto_dir $dir "device"

	local link=`get_link "device"`	
        if [[ -z $link ]]; then 
	    err $ERR_NO_SYSFS_DEVINFO
        fi

	get_hbtl $link
	cd $link

        # save the name of the current directory, we may need it later...
        local device_dir=${PWD##/*/}

	if [[ $TARGET = $DEV_TARGET && $LUN = $DEV_LUN ]]; then
	    goto_dir $PWD "devspec"
	    local devspec=`$CAT ./devspec 2>/dev/null`
	    if [[ $devspec = $DEVPATH ]]; then
	        LOGICAL_DEVNAME="${dir##*/}"
		return
	    fi

	    local scsi_name=${devspec##/*/}
	    scsi_name=${scsi_name%%@*}
	    if [[ $scsi_name != "scsi" ]]; then
		scsi_name=`get_scsi_host $device_dir`
		devspec=$devspec/$scsi_name
	        if [[ $devspec = $DEVPATH ]]; then
	            LOGICAL_DEVNAME="${dir##*/}"
		    return
	        fi
	    fi
	fi
    done
}

#
# Main 
#

if [[ "$#" -eq 0 ]]; then
    usage
    exit 0
fi

# default: convert logical => OFpath
do_of2l=0

getopt -o "l:Vqh" -l "help,version,quiet" $@ > /dev/null 2>&1
while [[ -n $1 ]]; do
    case "$1" in
        -l) 
	    do_of2l=1 
	    DEVNAME_ARG=$2
	    shift ;;
	-V | --version) 
	    show_version 
	    exit 0 ;;
	-q | --quiet)
	    be_quiet=1 ;;
	-h | --help) 
	    usage
	    exit 0 ;;
	*)
	    DEVNAME_ARG=$1 ;;
    esac
    shift
done

DEVNAME=$DEVNAME_ARG

# double check device name
if [[ -z $DEVNAME ]]; then
    usage
    exit 1
fi

# We need sysfs
if [[ ! -d "/sys" ]]; then
    err $ERR_NO_SYSFS
    exit 1
fi


if [[ $do_of2l = "0" ]]; then
    # logical devname => OF pathname
    logical_to_ofpathname
else
    # OF pathnmae => logical devname
    ofpathname_to_logical 
fi

exit 0

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-10-24  2:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-10-23 22:53 [PPC] quick test please? device tree path translation Hollis Blanchard
2005-10-24  0:19 ` Mike Small
2005-10-24  0:42   ` Hollis Blanchard
2005-10-24  0:46     ` Dennis Clarke
2005-10-24  2:04       ` Hollis Blanchard
2005-10-24  0:43   ` Dennis Clarke

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.