# -*- shell-script -*-

# 00minimal - Directory-based VPD creation functions.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 2004

# Maintained by  Martin Schwenke <martins@au.ibm.com>

# This program 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 2, or (at your option)
# any later version.
 
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    
# $Id: 00vpd,v 1.2 2004/05/20 07:58:58 martins Exp $

# This module is always loaded.
true || return 0

######################################################################

vpd_create_hook ()
{
    # Uses: ds, ax, mf, tm, sn, cd, rl, rm, yl

    local node="$1"

    local fc
    do_fc_hook "$node"

    local vpd_dir
    vpd_dir_set_hook "$node"

    _vpd_field_append "value" "$vpd_dir" "FC" "$fc"
    _vpd_field_append "value" "$vpd_dir" "DS" "$ds"
    _vpd_field_append "value" "$vpd_dir" "MF" "$mf"
    _vpd_field_append "value" "$vpd_dir" "TM" "$tm"
    _vpd_field_append "value" "$vpd_dir" "SN" "$sn"
    _vpd_field_append "value" "$vpd_dir" "CD" "$cd"
    _vpd_field_append "value" "$vpd_dir" "RL" "$rl"
    _vpd_field_append "value" "$vpd_dir" "RM" "$rm"
    _vpd_field_append "value" "$vpd_dir" "YL" "$yl"
}

vpd_field_add_value ()
{
    local dir="$1"
    local field="$2"
    local value="$3"

    ensure_directory "$dir"
    echo -n "$value"  >"${dir}/${field}"
}

vpd_field_add_link ()
{
    local dir="$1"
    local field="$2"
    local link="$3"

    ensure_directory "$dir"
    local f="${dir}/${field}"
    rm -f "$f"
    ln -s "$link" "$f"
}

_vpd_field_add ()
{
    local flag="$1"
    shift

    case "$flag" in
	(value) vpd_field_add_value "$@" ;;
	(link)  vpd_field_add_link  "$@" ;;
    esac
}

_vpd_field_append ()
{
    local flag="$1"
    local dir="$2"
    local field="$3"
    local value="$4"

    if [ -n "$value" ] ; then 
	_vpd_field_add "$flag" "$dir" "$field" "$value"
	echo -n "${field} " >>"${dir}/.lsvpd"
    fi
}

_vpd_field_insert ()
{
    local flag="$1"
    local dir="$2"
    local field="$3"
    local value="$4"

    local f="${dir}/.lsvpd"
    if [ ! -f "$f" ] ; then
	_vpd_field_append "$flag" "$dir" "$field" "$value"
    else
	local all
	read all <"$f"
	# Important trailing space lost above!
	all="${all} "

	case "$field" in
	    AX)
	        # Insert after DS, if possible.
		all="${all/DS /DS AX }"
		case "$all" in
		    (*DS\ AX*) : ;;
		    (*) all="${all}AX " ;;
		esac
		;;
	    ?*)
	        # Insert before YL, if possible.
		all="${all/YL /${field} YL }"
		case "$all" in
		    (*${field}\ YL*) : ;;
		    (*) all="${all}${field} " ;;
		esac
		;;
	esac

	echo "${all}" >"$f"
	_vpd_field_add "$flag" "$dir" "$field" "$value"
    fi
}

_vpd_field_ensure ()
{
    local flag="$1"
    local dir="$2"
    local field="$3"
    local value="$4"

    if [ ! -e "${dir}/${field}" ] ; then
	_vpd_field_insert "$flag" "$dir" "$field" "$value"
    else
	return 1
    fi
}

vpd_field_ensure ()
{
    _vpd_field_ensure "value" "$@"
}

vpd_field_ensure_link ()
{
    _vpd_field_ensure "link" "$@"
}

_vpd_field_override ()
{
    local flag="$1"
    local dir="$2"
    local field="$3"
    local value="$4"

    local f="${dir}/${field}"
    if [ -e "$f" ] ; then
	_vpd_field_add    "$flag" "$dir" "$field" "$value"
    else
	_vpd_field_insert "$flag" "$dir" "$field" "$value"
    fi
}

vpd_field_override ()
{
    _vpd_field_override "value" "$@"
}

vpd_field_override_link ()
{
    _vpd_field_override "link" "$@"
}

adapter_extra_vpd_hooks=""

adapter_extra_vpd_hook ()
{
    local type="$1"
    local bus_info="$2"
    local node="$3"

    local vpd_dir
    vpd_dir_set_hook "$node"

    local i
    for i in $adapter_extra_vpd_hooks ; do
	$i "$type" "$bus_info" "$vpd_dir"
    done
}
