/**
 * File:
 *      bootloader/ppc/iSeries.ycp
 *
 * Module:
 *      Bootloader installation and configuration
 *
 * Summary:
 *      include containing specific functions for iSeries configuration
 *      and installation
 *
 * Authors:
 *      Jiri Srain <jsrain@suse.cz>
 *
 * $Id: iseries.ycp 19973 2004-10-27 07:50:12Z jsrain $
 *
 */

{
    textdomain "bootloader";

    import "Kernel";
    import "Installation";
    import "Mode";

    import "BootCommon";

    include "bootloader/ppc/misc.ycp";
    include "bootloader/routines/popups.ycp";


// misc. functions

    /**
      * Get the type of target (just a simple heuristic)
      * @param target bootloader target
      * @return symbol `slot, `prep, `file or `unknown
      */
    global define symbol iSeriesTarget2Type (string target) ``{
	// one big letter means slot
	if (size (target) == 1 && target == toupper (target))
	{
	    return `slot;
	}
	// /dev/ at the beginning means device, hopefully PReP partition
	else if (substring (target, 0, 5) == "/dev/")
	{
	    return `prep;
	}
	// files should begin with the absolute path
	else if (substring (target, 0, 1) == "/")
	{
	    return `file;
	}
	// didn't realize what it is -> unknown
	return `unknown;
    }

    /**
      * Assign the Boot::activate variable
      */
    global define void iSeriesAssignDevice () ``{
	if ( !  ( iseries_write_prepboot ||
	    iseries_write_slot_b   ||
	    iseries_write_slot_a   ||
	    iseries_write_streamfile ) )
	{
	    BootCommon::activate = false;
	}
	else
	{
	    BootCommon::activate = true;
	}
     }


// general functions

    /**
      * Propose bootloader settings
      * @param initial boolean true if doing initial proposal
      */
    global define void iSeriesPropose (boolean initial) ``{
	if (BootCommon::was_proposed)
	{
	    return;
	}

	iseries_write_slot_a = true;
	iseries_write_slot_b = true;
	iseries_write_prepboot = true;
	iseries_write_streamfile = true;
	if ( ! (size (prep_boot_partitions) > 0))
	{
	    iseries_write_prepboot = false;
	}
    }

    /**
      * Read the board-type-specific settings
      * @return boolean true on success
      */
    global define boolean iSeriesRead () ``{
	prep_boot_partition = "/dev/null";
	iseries_streamfile = "";
	iseries_write_slot_b = false;
	iseries_write_prepboot = false;
	iseries_write_streamfile = false;
	foreach (map g, BootCommon::globals, ``{
	    if (g["key"]:"" == "boot")
	    {
		string target = g["value"]:"";
		symbol type = iSeriesTarget2Type (target);
		if (type == `slot)
		{
		    if (target == "A")
			iseries_write_slot_a = true;
		    else if (target == "B")
			iseries_write_slot_b = true;
		}
		else if (type == `prep)
		{
		    iseries_write_prepboot = true;
		    if (prep_boot_partition == "/dev/null")
		    {
			prep_boot_partition = target;
		    }
		}
		else if (type == `file)
		{
		    iseries_write_streamfile = true;
		    if (iseries_streamfile == "")
		    {
			iseries_streamfile = target;
		    }
		}
	    }
	});
	iSeriesAssignDevice ();
	return true;
    }

    /**
      * Update the board-type-specific settings
      * @return boolean true on success
      */
    global define boolean iSeriesUpdate () ``{
	prep_boot_partition = BootCommon::UpdateDevice (prep_boot_partition);
	return true;
    }

    /**
      * Save the board-type-specific settings
      * @return boolean true on success
      */
    global define boolean iSeriesSave () ``{
	BootCommon::globals = filter (map g, BootCommon::globals, ``(
	    g["key"]:"" != "boot"
	));
	if (iseries_write_slot_b)
	{
	    BootCommon::globals = add (BootCommon::globals, $[
		"key" : "boot",
		"value" : "B",
	    ]);
	}
	if (iseries_write_prepboot)
	{
	    BootCommon::globals = add (BootCommon::globals, $[
		"key" : "boot",
		"value" : prep_boot_partition,
	    ]);
	}
	if (iseries_write_streamfile)
	{
	    BootCommon::globals = add (BootCommon::globals, $[
		"key" : "boot",
		"value" : iseries_streamfile,
	    ]);
	}
	return true;
    }

    /**
      * retuen the board-type-specific part of summary
      * @return a list of summary strings
      */
    global define list<string> iSeriesSummary () ``{
	list<string> ret = [];
	if ( iseries_write_streamfile )
	{
	    ret = add (ret, sformat (
		// summary part, %1 is filename
		_("A stream file will be written to %1. Copy this file to OS400 side and boot with *STMF."),
		iseries_streamfile));
	}

	if ( iseries_write_prepboot )
	{
	    ret = add (ret, sformat(
		// summary part, %1 is filename
		_("The kernel will be written to %1. Use *NWSSTG on OS400 side."),
		prep_boot_partition));
	}

	if ( iseries_write_slot_b )
	{
	    // summary part
	    ret = add (ret, _("The kernel will be written to slot B."));
	}

	if ( iseries_write_slot_a )
	{
	    // summary part
	    ret = add (ret, ("A rescue kernel will be written to slot A."));
	}

	if ( iseries_write_slot_a || iseries_write_slot_b )
	{
	    // summarry part
	    ret = add (ret, _("This will take a while..."));
	}
	if ( BootCommon::activate == false )
	{
	    // summary part
	    ret = [
		_("No boot configuration. Configure booting manually.")
	    ];
	}
	if (! (iseries_write_prepboot || iseries_write_slot_b
	    || iseries_write_slot_a || iseries_write_streamfile))
	{
	    // summary part
	    ret = [ _("No boot option selected.") ];
	}
	y2milestone("prep_boot_partitions %1", prep_boot_partitions);
	return ret;
    }

    /**
      * Install the board-type-specific part of bootloader
      * @param requires_initrd boolean true if initrd is required
      * @return boolean true on success
      */
    global define boolean iSeriesWrite (boolean requires_initrd) ``{
	if (! BootCommon::activate)
	    return true;
	string iseries_bootbinary = "/boot/vmlinux64";
	if (requires_initrd)
	{
	    iseries_bootbinary = (string)SCR::Read (.target.tmpdir)
		+ "/vmlinux64.initrd";
	    SCR::Execute (.target.bash, "/lib/lilo/iseries/make_zimage_iseries.sh"
		+ " --vmlinux /boot/vmlinux --initrd /boot/initrd --output "
		+ iseries_bootbinary
		+ " >> /var/log/YaST2/y2loglilo_iseries_bootbinary 2>&1 " );
	}

	if ( iseries_write_slot_a )
	{
	    string rescue_bootbinary = iseries_bootbinary;
	    if (Stage::initial ())
	    {
		list<integer> sources = Pkg::SourceStartCache (true);
		integer source_id = sources[0]:0;
		string src_filename
		    = Pkg::SourceProvideFile(source_id, 1, "/ISERIES64");
		rescue_bootbinary = (string)SCR::Read (.target.tmpdir)
		    + "/rescue_bootbinary";
		string tg_rescue_bootbinary
		   = Installation::destdir + rescue_bootbinary;
		y2milestone ("Copying %1 to %2",
		    src_filename, tg_rescue_bootbinary);
		WFM::Execute (.local.bash, sformat ("/bin/cp %1 %2",
		    src_filename, tg_rescue_bootbinary));
	    }
	    y2milestone("start writing rescue kernel to slot A ...");
	    SCR::Execute (.target.bash, "time dd if=" + rescue_bootbinary
		+ " of=/proc/iSeries/mf/A/vmlinux bs=64k "
		+ ">>/var/log/YaST2/y2loglilo_iseries_slot_a 2>&1 ");
	    SCR::Execute (.target.bash, "dd if=/dev/zero of=/proc/iSeries/mf/A/cmdline bs=255 count=1");
	    SCR::Execute (.target.bash, "echo -en 'root=" + root_device
		+ " start_shell manual=1\\0' > /proc/iSeries/mf/A/cmdline");
	    y2milestone("done writing rescue kernel to slot A.");
	}

	return true;
    }

    /**
      * Initialize attributes of the board type
      */
    global define void iSeriesInit () ``{
	y2milestone ("Initializing iSeries attributes");
	prep_only_active = true;
	prep_only_iseries_vd = true;
	prep_only_primary = true;
	prep_same_disk_as_root = false;
	table_items = [ "__iseries_location" ];
    }



} // EOF
