/**
 * File:
 *      modules/BootS390.ycp
 *
 * Module:
 *      Bootloader installation and configuration
 *
 * Summary:
 *      Module containing specific functions for S390 configuration
 *      and installation
 *
 * Authors:
 *      Jiri Srain <jsrain@suse.cz>
 *
 * $Id: BootS390.ycp 22312 2005-03-07 12:33:03Z jsrain $
 *
 */

{
    module "BootS390";

    textdomain "bootloader";

    import "Kernel";
    import "StorageControllers";
    import "BootCommon";
    import "Mode";
    import "Stage";
    import "Installation";

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

// local data


    map<string,map<string,any> > hw_descr = $[
	"ctc" : $[
	    "skeleton": "hwcfg-ctc",
	    "target" : "ctc-bus-ccw-%1",
	    "options" : $[
		"CCW_CHAN_IDS" : "%1 %2",
		"CCW_CHAN_MODE" : "%3",
	    ],
	],
	"qeth" : $[
	    "skeleton" : "hwcfg-qeth",
	    "target" : "qeth-bus-ccw-%1",
	    "options" : $[
		"CCW_CHAN_IDS" : "%1 %2 %3",
		"CCW_CHAN_MODE" : "%4",
	    ],
	],
	"iucv" : $[
	    "skeleton" : "hwcfg-iucv",
	    "target" : "iucv-id-%1",
	],
    ];

// very simple UI - only select loader type

    /**
      * Create a list of options for the table
      * @param descr map description of the table
      * @return list of option ids as it should be displayed
      */
    global define list getTableContents (map descr) ``{
	return ["__loader_type"];
    }

    /**
      * Get map of widget
      * @return map of widget
      */
    global define map<string,any> getGlobalSectionWidget () ``{
	map<string,any> ret = BootCommon::getGlobalSectionWidget ();
	ret["ids"] = getTableContents;
	return ret;
    }

    /**
      * Get map of dialogs and widgets
      * @return map of dialogs and widgets
      */
    global define map<string,map<string,any> > GetWidgetMaps () ``{
	return $[
	    "globalsection" : getGlobalSectionWidget (),
	];
    }



// misc. functions

    /**
      * Update /etc/zip.conf before the update (fix kernel path)
      */
    global define void UpdateZiplConfBeforeUpdate () {
	// update the partition layout if needed
	// ?? FIXME any other conditions?
	if (Mode::update ())
	{
	    map output = (map)SCR::Execute (.target.bash_output, sformat (
	      "/bin/cp %1/etc/zipl.conf %1/etc/zipl.conf.YaST2save",
	      Installation::destdir));
	    y2milestone ("Result of backup original elilo.conf: %1", output);
	    output = (map)SCR::Execute (.target.bash_output, sformat (
		"/bin/cp /usr/lib/YaST2/bin/update_zipl_conf %1/usr/lib/YaST2/bin/",
		Installation::destdir
	    ));
	    y2milestone ("Result of copying from / to %1: %2",
		Installation::destdir,
		output
	    );
	    output = (map)SCR::Execute (.target.bash_output, sformat (
		"chroot %1 /usr/lib/YaST2/bin/update_zipl_conf",
		Installation::destdir));
	    if (output["exit"]:0 != 0)
	    {
		y2error ("Update of /etc/zipl.conf failed: %1", output);
	    }
	    else
	    {
		BootCommon::was_proposed = false;
		BootCommon::was_read = false;
	    }
	}
    }

    /**
      * Empty summary dialog
      * @return symbol always `back
      */
    global define symbol runSummaryDialog () ``{
	displayNoSupportPopup ();
	return `back;
    }

    /**
      * Update /etc/sysconfig/hardware configuration
      * Use data from install.inf file
      * @return boolean true on success
      */
    global define boolean updateHardwareConfig () ``{
	if (! Stage::initial () || Mode::update ())
	    return true;

	boolean failed = false;
	string cfg = (string)SCR::Read (.etc.install_inf.Hardware);
	y2milestone ("Read hardware configuration from install.inf: %1", cfg);
	list<string> l = splitstring (cfg, ";");
	foreach (string s, l, ``{
	    list<string> args = splitstring (s, ",");
	    args = maplist (string a, args, ``{
		while (a != "" && substring (a, 0, 1) == " ")
		    a = substring (a, 1);
		while (a != "" && substring (a, size (a) - 1, 1) == " ")
		    a = substring (a, 0, size (a) - 1);
		return a;
	    });
	    string key = args[0]:"";
	    string a1 = args[1]:"";
	    string a2 = args[2]:"";
	    string a3 = args[3]:"";
	    string a4 = args[4]:"";
	    if (key != "")
	    {
		map<string,any> descr = hw_descr[key]:$[];
		string src = (string)(descr["skeleton"]:"");
		string dst = sformat ((string)(descr["target"]:""),
		    a1, a2, a3, a4);
		y2milestone ("Template: %1, Target: %2", src, dst);
		string command = sformat (
    "/bin/cp /etc/sysconfig/hardware/skel/%1 /etc/sysconfig/hardware/hwcfg-%2",
		    src, dst);
		if (0 != SCR::Execute (.target.bash, command))
		{
		    Report::Error (
		        // error report
			_("Copying hardware configuration template failed."));
		    failed = true;
		}
		path p = add (.sysconfig.hardware.value, dst);
		foreach (string k, string v,
		    (map<string,string>)(descr["options"]:$[]),
		``{
		    path op = add (p, k);
		    v = sformat (v, a1, a2, a3, a4);
		    if (! SCR::Write (op, v))
			failed = true;
		});
	    }
	});
	if (! SCR::Write (.sysconfig.hardware, nil))
	    failed = true;;
	return failed;
    }


// general functions

    /**
      * Propose bootloader settings
      */
    global define void Propose () ``{
	BootCommon::DetectDisks ();
	string root_device = BootCommon::RootPartitionDevice;
	string parameters = sformat ("%1 root=%2 %3 %4 %5",
	    StorageControllers::dasdParam,
	    root_device,
	    BootCommon::GetAdditionalKernelParams (),
	    "selinux=0",
	    "TERM=dumb");

	BootCommon::globals = [];
	BootCommon::sections = [
	    [
		$[ "key" : "label", "value" : "defaultboot" ],
		$[ "key" : "default", "value" : "ipl" ],
	    ],
	    [
		$[ "key" : "label", "value" : "ipl" ],
		$[ "key" : "target", "value" : "/boot/zipl" ],
		$[ "key" : "image",
		   "value" : sformat ("/boot/%1", Kernel::GetBinary ()) ],
		$[ "key" : "ramdisk", "value" : "/boot/initrd" ],
		$[ "key" : "parameters", "value" : parameters ],
	    ],
	    [
		$[ "key" : "label", "value" : "dumpdasd" ],
		$[ "key" : "target", "value" : "/boot/zipl" ],
		$[ "key" : "dumpto", "value" : "/dev/dasd??" ],
	    ],
	    [
		$[ "key" : "label", "value" : "dumptape" ],
		$[ "key" : "target", "value" : "/boot/zipl" ],
		$[ "key" : "dumpto", "value" : "/dev/rtibm0" ],
	    ],
	];
    }

    /**
      * Read settings from disk
      * @return boolean true on success
      */
    global define boolean Read () ``{
	BootCommon::DetectDisks ();
	BootCommon::changed = true;
	boolean ret = BootCommon::Read ();
	y2error ("Read: %1", BootCommon::io_structure);
	return ret;
    }

    /**
      * Save all bootloader configuration files
      * @return boolean true if success
      */
    global define boolean Save () ``{
	y2milestone ("Saving S390 cfg. file");

map settings = $[
  "global":$[
    "default":"ipl",
    "menuname":"menu1",
    "prompt":1,
    "timeout":10
  ],
  "sections":[
    $[
      "append":"selinux=0 TERM=dumb elevator=cfq",
      "initrd":"/boot/initrd",
      "kernel":"/boot/image",
      "name":"ipl",
      "original_name":"ipl",
      "root":BootCommon::RootPartitionDevice,
      "target":"/boot/zipl",
      "type":"image"
    ],
    $[
      "append":"selinux=0 TERM=dumb",
      "initrd":"/boot/initrd",
      "kernel":"/boot/image",
      "name":"failsafe",
      "original_name":"ipl",
      "root":BootCommon::RootPartitionDevice,
      "target":"/boot/zipl",
      "type":"image"
    ],
    $[
      "dumpto":"/dev/dasd??",
      "name":"dumpdasd",
      "original_name":"dumpdasd",
      "target":"/boot/zipl",
      "type":"dump"
    ],
    $[
      "dumpto":"/dev/rtibm0",
      "name":"dumptape",
      "original_name":"dumptape",
      "target":"/boot/zipl",
      "type":"dump"
    ]
  ]
];
	SCR::Execute (.bootloader.agent_init, "zipl");
	SCR::Execute (.bootloader.disk_init, BootCommon::PrepareInitData ());
	SCR::Write (.bootloader.settings, settings);
	SCR::Execute (.bootloader.update);
	return true;



	boolean ret = BootCommon::Save ();

	integer exit = (integer)SCR::Execute (.target.bash,
	    "test -d /boot/zipl || mkdir -p /boot/zipl");
	ret =  ret && (exit == 0);

	if (Mode::normal ())
	    return ret;

	updateHardwareConfig ();
// chandev is obsolete, syscofnig/hardware is used instead
/*	// append chandev to /etc/chandev.conf
	string chandev = (string)SCR::Read(.etc.install_inf.Chandev);
	if( chandev == nil )
	{
	    chandev = "";
	}

	if (chandev != ""
	    && (SCR::Read (.target.size, "/etc/chandev.conf") == -1))
	{
	    ret = ret && (0 == SCR::Execute (.target.bash,
		"/bin/echo '"+chandev+"' >> /etc/chandev.conf"));
	}*/
	return ret;
    }

    /**
      * Display bootloader summary
      * @return a list of summary lines
      */
    global define list<string> Summary () ``{
	// summary
	return [_("Install S390 Boot Loader")];
    }

    /**
      * Update read settings to new version of configuration files
      */
    global define void Update () ``{
	y2milestone ("No update functionality implemented");
    }

    /**
      * Write bootloader settings to disk
      * @return boolean true on success
      */
    global define boolean Write () ``{
	string bl_command = "/sbin/zipl > /var/log/YaST2/y2logzipl 2>&1";
	string bl_logfile = "/var/log/YaST2/y2logzipl";
	return BootCommon::installBootLoader (bl_command, bl_logfile);
    }

    /**
      * Update bootlaoder configuration sequence
      * @param ws_data map of wizard sequencer data
      * @return map modified map of wizard sequencer data
      */
    global define map FixSequence (map ws_data) ``{
        map aliases = $[
	    "summary" : ``(BootS390::runSummaryDialog ()),
        ];
        ws_data["aliases"] = aliases;
        return ws_data;
    }

    /**
      * Get the list of all dump devices
      * @return list of all dump devices, as list of maps containg keys
      *  "label", "target" and "dumpto"
      */
    global define list<map<string,string> > GetDumpDevices () ``{
	list<map<string,string> > dd = maplist (list<map> d,
	    BootCommon::sections,
	``(
	    listmap (map e, d, ``(
		$[ e["key"]:"": e["value"]:"" ]
	    ))
	));
	return filter (map<string,string> s, dd, ``(
	    s["dumpto"]:"" != ""
	));
    }

    /**
      * Set the list of all dump devices
      * @param dump_devices list in the same form as result of GetDumpDevices ()
      */
    global define void SetDumpDevices (list<map<string,string> > dump_devices) {
	BootCommon::sections = filter (list<map> s, BootCommon::sections, ``(
	    lookup_value (s, "dumpto", "") == ""
	));
	dump_devices = maplist (map<string,string> d, dump_devices, ``{
	    if (d["dumpto"]:"" == "")
		return nil;
	    if (d["target"]:"" == "")
		d["target"] = "/boot/zipl";
	    if (d["label"]:"" == "")
		d["label"] = "dump" + filterchars (d["dumpto"]:"", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
	    return d;
	});
	dump_devices = filter (map<string,string> d, dump_devices,``(d != nil));
	list<list<map> > dd = maplist (map<string,string> d, dump_devices, ``(
	    (list<map>)maplist (string k, string v, d, ``(
		$[ "key" : k, "value" : v ]
	    ))
	));
	BootCommon::sections = (list<list<map> >)merge (BootCommon::sections, dd);
    }

    /**
      * Return map of provided functions
      * @return map map of functions (eg. $["write":``(BootS390::Write ())])
      */
    global define map<string, any> GetFunctions () ``{
	return $[
	    "read"	: BootS390::Read,
	    "propose"	: BootS390::Propose,
	    "save"	: BootS390::Save,
	    "summary"	: BootS390::Summary,
	    "update"	: BootS390::Update,
	    "write"	: BootS390::Write,
//	    "sequence"	: BootS390::FixSequence,
	];
    }

    /**
      * Initializer of S390 bootloader
      */
    global define void Initializer () ``{
	y2milestone ("Called S390 (zipl) initializer");
	BootCommon::current_bootloader_attribs = $[
	    "section_title" : "label",
	    "kernel_key" : "image",
	    "propose" : true,
	    "read" : true,
	    "scratch" : true,
	];
	// TODO no UI available yet
	BootCommon::cwm_options = (map<string, map<string,any> >)union (
	    BootCommon::GetOptionMaps (),
	    $[]);//BootS390::GetOptionMaps ());
	BootCommon::cwm_widgets = (map<string, map<string,any> >)union (
	    BootCommon::GetWidgetMaps (),
	    BootS390::GetWidgetMaps ());
    }


    /**
      * Constructor
      */
    global define void BootS390 () ``{
	BootCommon::bootloader_attribs["s390"] = $[
            "loader_name" : "zipl",
	    "required_packages" : [], // FIXME
	    "initializer" : BootS390::Initializer,
        ];
    }

}
