]> git.ozlabs.org Git - yaboot.git/blob - ybin/ofpath
be3f8cd4d8f55f2281acb9f56ffc802feb799cd1
[yaboot.git] / ybin / ofpath
1 #! /bin/sh
2
3 ###############################################################################
4 ##
5 ## ofpath: determine OpenFirmware path from unix device node
6 ## Copyright (C) 2000, 2001, 2002 Ethan Benson
7 ##
8 ## Portions based on show_of_path.sh:
9 ##
10 ## Copyright (C) 2000 Olaf Hering <olh@suse.de>
11 ## 
12 ## This program is free software; you can redistribute it and/or
13 ## modify it under the terms of the GNU General Public License
14 ## as published by the Free Software Foundation; either version 2
15 ## of the License, or (at your option) any later version.
16 ##
17 ## This program is distributed in the hope that it will be useful,
18 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ## GNU General Public License for more details.
21 ##
22 ## You should have received a copy of the GNU General Public License
23 ## along with this program; if not, write to the Free Software
24 ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25 ##
26 ###############################################################################
27
28 PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
29 PRG="${0##*/}"
30 VERSION=1.0.3-DEVEL_DO_NOT_DISTRIBUTE-patch-36
31 DEBUG=0
32 export LC_COLLATE=C
33
34 ## --version output.
35 version()
36 {
37 echo \
38 "$PRG $VERSION
39 Written by Ethan Benson
40 Portions based on show_of_path.sh written by Olaf Hering
41
42 Copyright (C) 2000, 2001, 2002 Ethan Benson
43 Portions Copyright (C) 2000 Olaf Hering
44 This is free software; see the source for copying conditions.  There is NO
45 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
46 }
47
48 ## --help output.
49 usage()
50 {
51 echo \
52 "Usage: $PRG [OPTION]... FILE
53 Find OpenFirmware device path from unix device node.
54
55       --debug                print boring junk only useful for debugging
56   -h, --help                 display this help and exit
57   -V, --version              output version information and exit"
58 }
59
60 ## a small seq replacement, seq is not present on boot/rescue floppies.
61 smallseq()
62 {
63     local v="$1"
64     local n=1
65     echo 1
66     while [ "$v" -gt 1 ] ; do
67         echo "$(($n + 1))"
68         local n="$(($n + 1))"
69         local v="$(($v - 1))"
70     done
71     return 0
72 }
73
74 ## a kludge to replace wc -l, wc is not present on boot/rescue
75 ## floppies. max file is 145 lines, 3 hosts * 16 devs each * 3 lines
76 ## per device, + 1 "Attached Devices:" line.
77 linecount()
78 {
79     if [ $# = 0 ] ; then
80         local file="$(cat)"
81         local v="$file"
82     else
83         local file="$(cat $1)"
84         local v="$file"
85     fi
86
87     if [ -z "$file" ] ; then
88         echo 0
89         return 0
90     fi
91
92     ## use real wc if available
93     if (command -v wc > /dev/null 2>&1) ; then
94         if [ -x `command -v wc` ] ; then
95             lines="$(echo "$file" | wc -l)"
96             if [ $? = 0 ] ; then
97                 echo $lines
98                 unset lines
99                 return 0
100             fi
101         fi
102     fi
103
104     while true ; do
105         for i in `smallseq 145` ; do
106             local b="$(echo "$file" | tail -n $i)"
107             if [ "$v" = "$b" ] ; then
108                 echo "$i"
109                 break 2
110             fi
111         done
112     done
113     return 0
114 }
115
116 ## small tr replacment which handles a specific need of this script.
117 smalltr()
118 {
119     case "$1" in 
120         a) echo 1 ;; b) echo 2 ;; c) echo 3 ;; d) echo 4 ;; e) echo 5 ;; f) echo 6 ;;
121         g) echo 7 ;; h) echo 8 ;; i) echo 9 ;; j) echo 10 ;; k) echo 11 ;; l) echo 12 ;;
122         m) echo 13 ;; n) echo 14 ;; o) echo 15 ;; p) echo 16 ;;
123         1) echo a ;; 2) echo b ;; 3) echo c ;; 4) echo d ;; 5) echo e ;; 
124         6) echo f ;; 7) echo g ;; 8) echo h ;; 9) echo i ;; 10) echo j ;;
125         11) echo k ;; 12) echo l ;; 13) echo m ;; 14) echo n ;; 15) echo o ;;
126         16) echo p ;;
127     esac
128     return 0
129 }
130
131 ## replacment for grep -l which is not supported by busybox grep.
132 ## echo $(cat..) hack needed because busybox grep barfs with `line too
133 ## long' when fed /proc files.  the for loop is needed since busybox
134 ## grep seems to have somewhat broken regexp support.
135 ## usage: lgrep filename regexp regexp ...
136 lgrep()
137 {
138     local f="$1"
139     shift
140     for i in "$@" ; do
141         echo "$(cat "$f")" | grep -q "$i" && echo "$f" && break
142     done
143     return 0
144 }
145
146 ## if readlink is missing use a kludge
147 if (command -v readlink > /dev/null 2>&1) ; then
148     true
149 else
150     readlink()
151     {
152         local SYMTARGET="$(v=`ls -l "$2" 2>/dev/null` ; echo ${v##*> })"
153         if [ -n "$SYMTARGET" ] ; then
154             echo "$SYMTARGET"
155             return 0
156         else
157             return 1
158         fi
159     }
160 fi
161
162 ## a function to print relevant scsi host path when there is more then
163 ## one.  this function also takes care of stripping off the trailing
164 ## /compatible.
165 printhost()
166 {
167     case "$1" in
168         1)
169         echo "${2%/*}"
170         ;;
171         2)
172         echo "${3%/*}"
173         ;;
174         3)
175         echo "${4%/*}"
176         ;;
177         4)
178         echo "${5%/*}"
179         ;;
180     esac
181     return 0
182 }
183
184 ## this finds information we need on both newworld and oldworld macs.
185 ## mainly what scsi host a disk is attached to.
186 scsiinfo()
187 {
188     ## see if system has scsi at all
189     if [ ! -f /proc/scsi/scsi ] ; then
190         echo 1>&2 "$PRG: /dev/$DEVNODE: Device not configured"
191         return 1
192     fi
193
194     ## first we have to figure out the SCSI ID, have to do that
195     ## anyway [to] find the attached scsi disks = "Direct-Access" and
196     ## stop at sda=1 sdb=2 or whatever count in 3 lines steps
197
198     ## get last letter of device node, ie sda -> a
199     SUBNODE=${DEVNODE##*sd}
200
201     ## turn SUBNODE above into a number starting at 1, ie a -> 1
202     SUBDEV="$(smalltr $SUBNODE)"
203     [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: SUBNODE=$SUBNODE SUBDEV=$SUBDEV"
204
205     DEVCOUNT=0
206
207     ## copy scsi file into a variable removing "Attached Devices"
208     ## which is the first line. this avoids a lot of
209     ## [incmopatible] crap later, and improves readability.
210
211     ## find number of lines once and recycle that number, to save
212     ## some time (linecount is a bit slow). subtract one line
213     ## to scrap Attached Devices:
214
215     SCSILINES="$(($(linecount /proc/scsi/scsi) - 1))"
216
217     if [ "$SUBDEV" -gt "$(cat /proc/scsi/scsi | grep Direct-Access | linecount)" ] ; then
218         echo 1>&2 "$PRG: /dev/$DEVNODE: Device not configured"
219         return 1
220     fi
221
222     PROCSCSI="$(cat /proc/scsi/scsi | tail -n $SCSILINES)"
223
224     for i in $(smallseq $(($SCSILINES / 3))) ; do
225
226         ## put every scsi device into one single line
227         DEVINFO="$(echo "$PROCSCSI" | head -n $(($i * 3)) | tail -n 3)"
228         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVINFO=$DEVINFO"
229
230         ## cut the type field, expect "Direct-Access" later.
231         DEVTYPE="$(v=$(echo ${DEVINFO##*Type: }) ; echo ${v%% *})"
232         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVTYPE=$DEVTYPE"
233
234         ## get the device id.
235         DEVID="$(v=$(echo ${DEVINFO##*Id: }) ; n=$(echo ${v%% *}) ; echo ${n#*0})"
236         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVID=$DEVID"
237
238         ## get the scsi host id.
239         DEVHOST="$(v=$(echo ${DEVINFO##*Host: scsi}) ; echo ${v%% *})"
240         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVHOST=$DEVHOST"
241
242         if [ "$DEVTYPE" = "Direct-Access" ] ; then
243             DEVCOUNT="$(($DEVCOUNT + 1))"
244             [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVCOUNT=$DEVCOUNT"
245             if [ "$SUBDEV" = "$DEVCOUNT" ] ; then
246                 DEVICE_HOST=$DEVHOST
247                 DEVICE_ID=$DEVID
248                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVICE_HOST=$DEVICE_HOST"
249                 break
250             fi
251         fi
252     done
253
254     ## figure out what the scsi driver is, it is /proc/scsi/dirname.
255     [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVICE_HOST=$DEVICE_HOST"
256     SCSI_DRIVER="$(x=`ls /proc/scsi/*/$DEVICE_HOST 2>/dev/null | cat` ; y=`echo ${x##*proc/scsi/}` ; echo ${y%%/*})"
257     [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: SCSI_DRIVER=$SCSI_DRIVER"
258
259     ## figure out which host we found.
260     SCSI_HOSTNUMBER="$(v=`ls /proc/scsi/$SCSI_DRIVER/* 2>/dev/null | cat | grep -n "$DEVICE_HOST\>"` ; echo ${v%%:*})"
261     [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: SCSI_HOSTNUMBER=$SCSI_HOSTNUMBER"
262
263     return 0
264 }
265
266 ## generic function that can find OF device paths for scsi devices,
267 ## must be run after scsiinfo().
268 scsi_ofpath()
269 {
270     case "$SCSI_DRIVER" in
271         aic7xxx)
272             HOST_LIST="$(for i in `find /proc/device-tree -name compatible` ; do
273                         lgrep "$i" "^ADPT" "^pci900[45]" "^pciclass,01000" ; done)"
274             DEVICE_PATH="$(printhost $SCSI_HOSTNUMBER $HOST_LIST)"
275             echo "${DEVICE_PATH##*device-tree}/@$DEVICE_ID:$PARTITION"
276             ;;
277         sym53c8xx)
278             HOST_LIST="$(for i in `find /proc/device-tree -name compatible` ; do
279                         lgrep "$i" "^Symbios" "^pci1000" "^pciclass,01000" ; done)"
280             DEVICE_PATH="$(printhost $SCSI_HOSTNUMBER $HOST_LIST)"
281             echo "${DEVICE_PATH##*device-tree}/@$DEVICE_ID:$PARTITION"
282             ;;
283         mesh)
284             HOST_LIST="$(for i in `find /proc/device-tree -name compatible` ; do
285                         lgrep "$i" "mesh" ; done)"
286             DEVICE_PATH="$(printhost $SCSI_HOSTNUMBER $HOST_LIST)"
287             echo "${DEVICE_PATH##*device-tree}/@$DEVICE_ID:$PARTITION"
288             ;;
289         *)
290             echo 1>&2 "$PRG: Driver: $SCSI_DRIVER is not supported"
291             return 1
292             ;;
293     esac
294     return 0
295 }
296
297 ide_ofpath()
298 {
299     if [ ! -L "/proc/ide/$DEVNODE" ] ; then
300         echo 2>&1 "$PRG: /dev/$DEVNODE: Device not configured"
301         return 1
302     fi
303
304     local IDEBUS="$(v=`readlink /proc/ide/$DEVNODE` ; echo ${v%%/*} )"
305     local OF1275IDE="/proc/ide/$IDEBUS/devspec"
306
307     if [ ! -f "$OF1275IDE" ] ; then
308         case "$(cat /proc/device-tree/model)" in
309             "PowerMac3,6")
310                 local CDROM="$(grep "^drive name:" /proc/sys/dev/cdrom/info 2> /dev/null | grep $DEVNODE)"
311                 if [ -z "$CDROM" ] ; then
312                     echo "ultra2:$PARTITION"
313                 else
314                     echo "cd:$PARTITION"
315                 fi
316                 ;;
317             *)
318                 if [ ! -L "/proc/ide/$DEVNODE" ] ; then
319                     echo "$PRG: /dev/$DEVNODE: Device not configured"
320                     return 1
321                 fi
322                 local CDROM="$(grep "^drive name:" /proc/sys/dev/cdrom/info 2> /dev/null | grep $DEVNODE)"
323                 if [ -z "$CDROM" ] ; then
324                     if [ "$DEVNODE" = hda ] ; then
325                         echo "hd:$PARTITION"
326                     else
327                         echo "ultra1:$PARTITION"
328                     fi
329                 else
330                     echo "cd:$PARTITION"
331                 fi
332                 ;;
333         esac
334     else
335         local DEVSPEC="$(cat /proc/ide/$IDEBUS/devspec)"
336         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: DEVSPEC=$DEVSPEC"
337         case "$DEVNODE" in
338             hda|hdc|hde|hdg|hdi)
339                 echo "${DEVSPEC}/disk@0:$PARTITION"
340                 return 0
341                 ;;
342             hdb|hdd|hdf|hdh|hdj)
343                 echo "${DEVSPEC}/disk@1:$PARTITION"
344                 return 0
345                 ;;
346             *)
347                 echo 1>&2 "$PRG: /dev/$DEVNODE is not supported"
348                 return 1
349                 ;;
350         esac
351     fi
352 }
353
354 ## figure out the OpenFirmware device path for newworld macs.
355 ## sd* scsi disks , hd* ide disks.
356 newworld()
357 {
358     case "$DEVNODE" in
359         sd*)
360             if ls -l /proc/device-tree | grep -q ^lr ; then
361                 true
362             else
363                 echo 1>&2 "$PRG: /proc/device-tree is broken.  Do not use BootX to boot, use yaboot."
364                 echo 1>&2 "$PRG: The yaboot HOWTO can be found here: http://www.alaska.net/~erbenson/doc"
365                 return 1
366             fi
367
368             ## use common scsiinfo function to get info we need.
369             scsiinfo || return 1
370
371             ## now we have the data for /@$DEVID:$PARTITION
372             ## find the actual OF path. 
373             scsi_ofpath || return 1
374             ;;
375         hd*)
376             ide_ofpath || return 1
377             ;;
378         *)
379             echo 1>&2 "$PRG: Device: /dev/$DEVNODE is not supported"
380             return 1
381             ;;
382     esac
383     return 0
384 }
385
386 oldworld()
387 {
388     ## for some reason 2.4 kernels put OF aliases in aliases@0/ instead of plain aliases/
389     if [ -d "/proc/device-tree/aliases" ] ; then
390         local ALIASES="aliases"
391     elif [ -d "/proc/device-tree/aliases@0" ] ; then
392         local ALIASES="aliases@0"
393     else
394         echo 1>&2 "$PRG: Cannot find OpenFirmware aliases directory in /proc/device-tree/"
395         return 1
396     fi
397
398     local MODEL="$(cat /proc/device-tree/compatible)"
399     [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: Oldworld subarch: $MODEL"
400
401     case "$MODEL" in
402         AAPL,7300*|AAPL,7500*|AAPL,8500*|AAPL,9500*|AAPL,\?\?\?\?*)
403             case "$DEVNODE" in
404                 sd*)
405                 scsiinfo || return 1
406                 case "$SCSI_DRIVER" in
407                     mesh)
408                     echo $(cat /proc/device-tree/$ALIASES/scsi-int)/sd\@$DEVICE_ID:$PARTITION
409                     ;;
410                     53c94)
411                     echo $(cat /proc/device-tree/$ALIASES/scsi)/sd\@$DEVICE_ID:$PARTITION
412                     ;;
413                     *)
414                     echo 1>&2 "$PRG: Driver $SCSI_DRIVER is not supported"
415                     return 1
416                     ;;
417                 esac
418                 ;;
419                 *)
420                 echo 1>&2 "$PRG: Unsupported device: /dev/$DEVNODE"
421                 return 1
422                 ;;
423             esac
424             ;;
425         AAPL,e407*)
426             case "$DEVNODE" in
427                 sd*)
428                 scsiinfo || return 1
429                 case "$SCSI_DRIVER" in
430                     mesh)
431                     echo $(cat /proc/device-tree/$ALIASES/scsi)/sd\@$DEVICE_ID:$PARTITION
432                     ;;
433                     *)
434                     echo 1>&2 "$PRG: Driver $SCSI_DRIVER is not supported"
435                     return 1
436                     ;;
437                 esac
438                 ;;
439                 hda*)
440                 echo $(cat /proc/device-tree/$ALIASES/ata)/ATA-Disk\@0:$PARTITION
441                 ;;
442                 hdb*)
443                 echo $(cat /proc/device-tree/$ALIASES/ata)/ATA-Disk\@1:$PARTITION
444                 ;;
445                 hd*)
446                 echo 1>&2 "$PRG: Device: /dev/$DEVNODE is not supported"
447                 ;;
448             esac
449             ;;
450         AAPL,e826*)
451             case "$DEVNODE" in
452                 sd*)
453                 scsiinfo || return 1
454                 case "$SCSI_DRIVER" in
455                     mesh)
456                     echo $(cat /proc/device-tree/$ALIASES/scsi)/sd\@$DEVICE_ID:$PARTITION
457                     ;;
458                     *)
459                     echo 1>&2 "$PRG: Driver $SCSI_DRIVER is not supported"
460                     return 1
461                     ;;
462                 esac
463                 ;;
464                 hda*)
465                 echo $(cat /proc/device-tree/$ALIASES/ata)/ata-disk\@0:$PARTITION
466                 ;;
467                 hdb*)
468                 echo $(cat /proc/device-tree/$ALIASES/ata)/ata-disk\@1:$PARTITION
469                 ;;
470                 hd*)
471                 echo 1>&2 "$PRG: Device: /dev/$DEVNODE is not supported"
472                 ;;
473             esac
474             ;;
475         AAPL,Gossamer*|AAPL,PowerMac\ G3*)
476             case "$DEVNODE" in
477                 sd*)
478                 scsiinfo || return 1
479                 case "$SCSI_DRIVER" in
480                     mesh)
481                     echo $(cat /proc/device-tree/$ALIASES/scsi)/sd\@$DEVICE_ID:$PARTITION
482                     ;;
483                     *)
484                     echo 1>&2 "$PRG: Driver $SCSI_DRIVER is not supported"
485                     return 1
486                     ;;
487                 esac
488                 ;;
489                 hda*)
490                 echo $(cat /proc/device-tree/$ALIASES/ide0)/ata-disk\@0:$PARTITION
491                 ;;
492                 hdb*)
493                 echo $(cat /proc/device-tree/$ALIASES/ide0)/ata-disk\@1:$PARTITION
494                 ;;
495                 hdc*)
496                 echo $(cat /proc/device-tree/$ALIASES/ide1)/ata-disk\@0:$PARTITION
497                 ;;
498                 hdd*)
499                 echo $(cat /proc/device-tree/$ALIASES/ide1)/ata-disk\@1:$PARTITION
500                 ;;
501                 hd*)
502                 echo 1>&2 "$PRG: Device: /dev/$DEVNODE is not supported"
503                 ;;
504             esac
505             ;;
506         AAPL,PowerBook1998*)
507             if [ -f  /proc/device-tree/$ALIASES/ata0 ] ; then
508                 local ATA0=ata0
509             else
510                 local ATA0=ide0
511             fi
512             if [ -f  /proc/device-tree/$ALIASES/ata1 ] ; then
513                 local ATA1=ata1
514             else
515                 local ATA1=bay-ata1
516             fi
517             case "$DEVNODE" in
518                 sd*)
519                 scsiinfo || return 1
520                 case "$SCSI_DRIVER" in
521                     mesh)
522                     echo $(cat /proc/device-tree/$ALIASES/scsi)/sd\@$DEVICE_ID:$PARTITON
523                     ;;
524                     *)
525                     echo 1>&2 "$PRG: Driver $SCSI_DRIVER is not supported"
526                     return 1
527                     ;;
528                 esac
529                 ;;
530                 hda*)
531                 echo $(cat /proc/device-tree/$ALIASES/$ATA0)/ata-disk\@0:$PARTITION
532                 ;;
533                 hdb*)
534                 echo $(cat /proc/device-tree/$ALIASES/$ATA0)/ata-disk\@1:$PARTITION
535                 ;;
536                 hdc*)
537                 echo $(cat /proc/device-tree/$ALIASES/$ATA1)/atapi-disk\@0:$PARTITION
538                 ;;
539                 hdd*)
540                 echo $(cat /proc/device-tree/$ALIASES/$ATA1)/atapi-disk\@1:$PARTITION
541                 ;;
542                 *)
543                 echo 1>&2 "$PRG: Unsupported device: /dev/$DEVNODE"
544                 return 1
545                 ;;
546             esac
547             ;;
548         AAPL,3400/2400*)
549             case "$DEVNODE" in
550                 sd*)
551                 scsiinfo || return 1
552                 case "$SCSI_DRIVER" in
553                     mesh)
554                     echo $(cat /proc/device-tree/$ALIASES/scsi-int)/sd\@$DEVICE_ID:$PARTITON
555                     ;;
556                     53c94)
557                     echo $(cat /proc/device-tree/$ALIASES/scsi)/sd\@$DEVICE_ID:$PARTITON
558                     ;;
559                     *)
560                     echo 1>&2 "$PRG: Driver $SCSI_DRIVER is not supported"
561                     return 1
562                     ;;
563                 esac
564                 ;;
565                 hda*)
566                 echo $(cat /proc/device-tree/$ALIASES/ata0)/ata-disk\@0:$PARTITION
567                 ;;
568                 hdb*)
569                 echo $(cat /proc/device-tree/$ALIASES/ata0)/ata-disk\@1:$PARTITION
570                 ;;
571                 hdc*)
572                 echo $(cat /proc/device-tree/$ALIASES/ata1)/atapi-disk\@0:$PARTITION
573                 ;;
574                 hdd*)
575                 echo $(cat /proc/device-tree/$ALIASES/ata1)/atapi-disk\@1:$PARTITION
576                 ;;
577                 hde*)
578                 echo $(cat /proc/device-tree/$ALIASES/ata2):$PARTITION
579                 ;;
580                 hdf*)
581                 echo $(cat /proc/device-tree/$ALIASES/ata3):$PARTITION
582                 ;;
583                 *)
584                 echo 1>&2 "$PRG: Unsupported device: /dev/$DEVNODE"
585                 return 1
586                 ;;
587             esac
588             ;;
589         *)
590             echo 1>&2 "$PRG: This machine is not supported: $MODEL"
591             return 1
592             ;;
593     esac
594     return 0
595 }
596
597 ## find OpenFirmware device path for IBM CHRP hardware (scsi only)
598 chrp()
599 {
600     case "$DEVNODE" in
601         sd*)
602             if ls -l /proc/device-tree | grep -q ^lr ; then
603                 true
604             else
605                 echo 1>&2 "$PRG: /proc/device-tree is broken."
606                 return 1
607             fi
608
609             ## use common scsiinfo function to get info we need.
610             scsiinfo || return 1
611
612             ## now we have the data for /@$DEVID:$PARTITION
613             ## find the actual OF path. 
614             scsi_ofpath || return 1
615             ;;
616         *)
617             echo 1>&2 "$PRG: Device: /dev/$DEVNODE is not supported"
618             return 1
619             ;;
620     esac
621     return 0
622 }
623
624 ## If we get lame devfs name, we need to make it foad
625 ckdevfs()
626 {
627     case "$1" in
628         /dev/ide/*|/dev/scsi/*|/dev/discs/*)
629         return 0
630         ;;
631         *)
632         return 1
633         ;;
634     esac
635 }
636
637 ## convert devfs names into normal short ones, written by Tom Rini.
638 fixdevfs()
639 {
640     ## get partition number, if any
641     local PARTNUM="${1##*[a-z]}"
642     ## Find the bus type.
643     local TYPE="$(v=${1#/dev/} ; echo ${v%/host*})"
644     ## Find the host number.
645     local HOST="$(v=${1#/dev/*/host} ; echo ${v%/bus*})"
646     ## Find the bus number.
647     local BUS="$(v=${1#/dev/*/bus} ; echo ${v%/tar*})"
648     ## Find the target.
649     local TARGET="$(v=${1#/dev/*/target} ; echo ${v%/lun*})"
650
651     case "$TYPE" in
652         ide)
653         case "$HOST" in
654             0)
655             case "$TARGET" in
656                 0)
657                 local DEV=hda
658                 ;;
659                 1)
660                 local DEV=hdb
661                 ;;
662             esac
663             ;;
664             1)
665             case "$TARGET" in
666                 0)
667                 local DEV=hdc
668                 ;;
669                 1)
670                 local DEV=hdd
671                 ;;
672             esac
673             ;;
674             *)
675                 echo 1>&2 "$PRG: $1: Unable to translate this device, try again without devfs."
676                 return 1
677         esac
678         local DEV="${DEV}${PARTNUM}"
679         echo "/dev/$DEV"
680         return 0
681         ;;
682         scsi)
683         local LUN="$(v=${1#/dev/*/lun} ; echo ${v%/*})"
684
685         ## In this case, we need to figure out what number our device is
686         local DEVCOUNT=0
687
688         ## copy scsi file into a variable removing "Attached Devices"
689         ## which is the first line. this avoids a lot of
690         ## [incmopatible] crap later, and improves readability.
691
692         ## find number of lines once and recycle that number, to save
693         ## some time (linecount is a bit slow). subtract one line
694         ## to scrap Attached Devices:
695
696         local SCSILINES="$(($(linecount /proc/scsi/scsi) - 1))"
697         local PROCSCSI="$(cat /proc/scsi/scsi | tail -n $SCSILINES)"
698
699         for i in $(smallseq $(($SCSILINES / 3))) ; do
700
701             ## put every scsi device into one single line
702             local DEVINFO="$(echo "$PROCSCSI" | head -n $(($i * 3)) | tail -n 3)"
703             [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: fixdevfs: DEVINFO=$DEVINFO"
704
705             ## cut the type field, expect "Direct-Access" later.
706             local DEVTYPE="$(v=$(echo ${DEVINFO##*Type: }) ; echo ${v%% *})"
707             [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: fixdevfs: DEVTYPE=$DEVTYPE"
708
709             if [ "$DEVTYPE" = "Direct-Access" ] ; then
710                 ## Lets find out some more information
711                 ## get the device id.
712                 local DEVID="$(v=$(echo ${DEVINFO##*Id: }) ; n=$(echo ${v%% *}) ; echo ${n#*0})"
713                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: fixdevfs: DEVID=$DEVID"
714
715                 ## get the device lun.
716                 local DEVLUN="$(v=$(echo ${DEVINFO##*Lun: }) ; n=$(echo ${v%% *}) ; echo ${n#*0})"
717                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: fixdevfs: DEVLUN=$DEVLUN"
718
719                 ## get the device channel.
720                 local DEVCHAN="$(v=$(echo ${DEVINFO##*Channel: }) ; n=$(echo ${v%% *}) ; echo ${n#*0})"
721                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: fixdevfs: DEVCHAN=$DEVCHAN"
722
723                 ## get the scsi host id.
724                 local DEVHOST="$(v=$(echo ${DEVINFO##*Host: scsi}) ; echo ${v%% *})"
725                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: fixdevfs: DEVHOST=$DEVHOST"
726
727                 local DEVCOUNT="$(($DEVCOUNT + 1))"
728                 [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: fixdevfs: DEVCOUNT=$DEVCOUNT"
729                 if [ "$DEVHOST" = "$HOST" -a "$DEVCHAN" = "$BUS" -a \
730                     "$DEVID" = "$TARGET" -a "$DEVLUN" = "$LUN" ] ; then
731                     local DEV="sd$(smalltr $DEVCOUNT)${PARTNUM}"
732                     echo "/dev/$DEV"
733                     return 0
734                 fi
735             fi
736         done
737         echo 1>&2 "$PRG: $1: Unable to translate this device, try again without devfs."
738         return 1
739         ;;
740         *)
741         echo 1>&2 "$PRG: Unknown bus $TYPE"
742         return 1
743         ;;
744     esac
745     ## we should never get here
746     return 1
747 }
748
749 ## make sure that find, head and tail can be found.  otherwise the
750 ## script will silently give bogus paths.  these are the only /usr/*
751 ## utilities this script depends on.
752 checkutils()
753 {
754     if command -v find > /dev/null 2>&1 ; then
755         [ -x `command -v find` ] || FAIL=1 ; else FAIL=1 ; fi
756     if command -v head > /dev/null 2>&1 ; then
757         [ -x `command -v head` ] || FAIL=1 ; else FAIL=1 ; fi
758     if command -v tail > /dev/null 2>&1 ; then
759         [ -x `command -v tail` ] || FAIL=1 ; else FAIL=1 ; fi
760
761     if [ "$FAIL" = 1 ] ; then
762         echo 1>&2 "$PRG: \`find', \`head', or \`tail' could not be found, aborting."
763         return 1
764     else
765         return 0
766     fi
767 }
768
769 ## parse command line switches.
770 if [ $# != 0 ] ; then
771     while true ; do
772         case "$1" in
773             -V|--version)
774                 version
775                 exit 0
776                 ;;
777             -h|--help)
778                 usage
779                 exit 0
780                 ;;
781             --debug)
782                 DEBUG=1
783                 shift
784                 ;;
785             -*)
786                 echo 1>&2 "$PRG: unrecognized option \`$1'"
787                 echo 1>&2 "$PRG: Try \`$PRG --help' for more information."
788                 exit 1
789                 ;;
790             "")
791                 echo 1>&2 "$PRG: You must specify a filename"
792                 echo 1>&2 "Try \`$PRG --help' for more information."
793                 exit 1
794                 ;;
795             *)
796                 device="$1"
797                 break
798                 ;;
799         esac
800     done
801 else
802     echo 1>&2 "$PRG: You must specify a /dev device"
803     echo 1>&2 "Try \`$PRG --help' for more information."
804     exit 1
805 fi
806
807 ## check that FILE is a block device and exists.
808 if [ ! -e "$device" ] ; then
809     echo 1>&2 "$PRG: $device: No such file or directory"
810     exit 1
811 elif [ ! -b "$device" ] ; then
812     echo 1>&2 "$PRG: $device is not a block device"
813     exit 1
814 fi
815
816 ## check that we are running on a GNU/Linux system, OSX/BSD does not
817 ## have the same /proc stuff
818 if [ `uname -s` != Linux ] ; then
819     echo 1>&2 "$PRG: This utility will only work with GNU/Linux"
820     exit 1
821 fi
822
823 ## check for ppc, i think uname -m is safe for this...
824 if [ `uname -m` != ppc ] ; then
825     echo 1>&2 "$PRG: This utility will only work on PowerPC hardware"
826     exit 1
827 fi
828
829 ## ofpath cannot live without procfs
830 if [ ! -f /proc/uptime ] ; then
831     echo 1>&2 "$PRG: This utility requires the /proc filesystem"
832     exit 1
833 fi
834
835 ## check for retarded devfs names and tell them to foad.
836 if ckdevfs "$device" ; then
837     device="$(fixdevfs $device)" || exit 1
838 fi
839
840 ## check for newworld mac. use cat hack due to /proc wierdness.
841 if [ "$(v=`cat /proc/cpuinfo 2>/dev/null | grep pmac-generation` ; echo ${v##*:[ ]})" = NewWorld ] ; then
842     SUBARCH=NewWorld
843 elif [ "$(v=`cat /proc/cpuinfo 2>/dev/null | grep pmac-generation` ; echo ${v##*:[ ]})" = OldWorld ] ; then
844     SUBARCH=OldWorld
845 elif (cat /proc/cpuinfo 2>/dev/null | grep ^motherboard | grep -q AAPL) ; then
846     SUBARCH=OldWorld
847 elif (cat /proc/cpuinfo 2> /dev/null | grep ^machine | grep -q 'CHRP IBM') ; then
848     SUBARCH=CHRP
849 else
850     echo 1>&2 "$PRG: This machine is not yet supported"
851     exit 1
852 fi
853
854 ## make sure /proc/device-tree exists
855 if [ ! -d /proc/device-tree ] ; then
856     echo 1>&2 "$PRG: /proc/device-tree does not exist"
857     echo 1>&2 "$PRG: Make sure you compiled your kernel with CONFIG_PROC_DEVICETREE=y"
858     exit 1
859 fi
860
861 ## make sure we have what we need.
862 checkutils || exit 1
863
864 ## get the base device node and scrap /dev/ ie /dev/hda2 -> hda
865 DEVICE="${device##*/}"
866 DEVNODE="${DEVICE%%[0-9]*}"
867 PARTITION="${DEVICE##*[a-z]}"
868
869 ## use appropriate search for right sub arch.
870 case "$SUBARCH" in
871     NewWorld)
872         newworld || exit 1
873         ;;
874     OldWorld)
875         oldworld || exit 1
876         ;;
877     CHRP)
878         chrp || exit 1
879         ;;
880 esac
881
882 exit 0