home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / modules / Bootloader.ycp < prev    next >
Text File  |  2006-11-29  |  29KB  |  1,003 lines

  1. /**
  2.  * File:
  3.  *      modules/Bootloader.ycp
  4.  *
  5.  * Module:
  6.  *      Bootloader installation and configuration
  7.  *
  8.  * Summary:
  9.  *      Bootloader installation and configuration base module
  10.  *
  11.  * Authors:
  12.  *      Jiri Srain <jsrain@suse.cz>
  13.  *
  14.  * $Id: Bootloader.ycp 34538 2006-11-21 13:55:48Z odabrunz $
  15.  *
  16.  */
  17.  
  18. {
  19.     module "Bootloader";
  20.  
  21.     textdomain "bootloader";
  22.  
  23.     import "Arch";
  24.     import "BootCommon";
  25.     import "Installation";
  26.     import "Initrd";
  27.     import "Kernel";
  28.     import "Mode";
  29.     import "Progress";
  30.     import "Stage";
  31.     import "Storage";
  32.  
  33. //    import "BootABOOT";
  34.     import "BootELILO";
  35.     import "BootLILO";
  36. //    import "BootMILO";
  37. //    import "BootS390";
  38.     import "BootGRUB";
  39.     import "BootPOWERLILO"; // The ppc-LILO File
  40.  
  41.     global define map Export ();
  42.     global define boolean Import (map<string,any> settings);
  43.     global define void Propose ();
  44.     global define boolean Read ();
  45.     global define void Reset ();
  46.     global define boolean Write ();
  47.  
  48.     global define void ReadOrProposeIfNeeded ();
  49.     global define string getDefaultSection ();
  50.     global define string getKernelParam (string section, string key);
  51.     global define boolean setKernelParam (string section, string key, string value);
  52.     global define list<string> listKernelParams (string section);
  53.     global define string getLoaderType ();
  54.     global define string getProposedDefaultSection ();
  55.     global define boolean UpdateGfxMenu ();
  56.  
  57.  
  58.     /**
  59.       * Write is repeating again
  60.       * Because of progress bar during inst_finish
  61.       */
  62.     global boolean repeating_write = false;
  63.  
  64. // installation proposal help variables
  65.  
  66.     /**
  67.       * Configuration was changed during inst. proposal if true
  68.       */
  69.     global boolean proposed_cfg_changed = false;
  70.  
  71.     /**
  72.      * Cache for the installation proposal
  73.      */
  74.     global map cached_proposal = nil;
  75.     global map cached_settings = $[];
  76.     global integer cached_settings_base_data_change_time = nil;
  77.  
  78. // old vga value handling function
  79.  
  80.     /**
  81.       * old value of vga parameter of default bootloader section
  82.       */
  83.     string old_vga = nil;
  84.  
  85. // UI helping variables
  86.  
  87.     global map aliases = $[];
  88.     global map ws_data = $[];
  89.  
  90.     include "bootloader/routines/switcher.ycp";
  91.     include "bootloader/routines/popups.ycp";
  92.  
  93.  
  94. // general functions
  95.  
  96.     global boolean() test_abort = nil;
  97.  
  98.     /**
  99.      * Check whether abort was pressed
  100.      * @return boolean true if abort was pressed
  101.      */
  102.     boolean testAbort () {
  103.         if (test_abort == nil)
  104.         return false;
  105.         return test_abort ();
  106.     }
  107.  
  108.     /**
  109.       * Constructor
  110.       */
  111.     global define void Bootloader () {
  112.     return;
  113.     }
  114.  
  115.     /**
  116.       * Export bootloader settings to a map
  117.       * @return bootloader settings
  118.       */
  119.     global define map Export () {
  120.     ReadOrProposeIfNeeded ();
  121.     map out = $[
  122.         "loader_device" : BootCommon::loader_device,
  123.         "loader_location" : BootCommon::selected_location,
  124.         "loader_type" : getLoaderType (),
  125.         "initrd" : Initrd::Export (),
  126.         "specific" : blExport (),
  127.         "write_settings" : BootCommon::write_settings,
  128.     ];
  129.     y2milestone ("Exporting settings: %1", out);
  130.     return out;
  131.     }
  132.     /**
  133.       * Import settings from a map
  134.       * @param settings map of bootloader settings
  135.       * @return boolean true on success
  136.       */
  137.     global define boolean Import (map<string, any> settings) {
  138.     y2milestone ("Importing settings: %1", settings);
  139.     Reset ();
  140.  
  141.     BootCommon::was_read = true;
  142.     BootCommon::was_proposed = true;
  143.     BootCommon::changed = true;
  144.     BootCommon::location_changed = true;
  145.  
  146.     if (settings["loader_type"]:nil == "")
  147.         settings["loader_type"] = nil;
  148.     string loader_type = (string) (settings["loader_type"]:nil);
  149.     BootCommon::setLoaderType (loader_type);
  150.     BootCommon::getLoaderType (false);
  151.  
  152.     BootCommon::loader_device = settings["loader_device"]:"";
  153.     BootCommon::selected_location = settings["loader_location"]:"custom";
  154.     if (loader_type == "lilo" || loader_type == "grub"
  155.         || Arch::i386 () || Arch::x86_64 ())
  156.     {
  157.         BootCommon::loader_device = BootCommon::GetBootloaderDevice ();
  158.     }
  159.  
  160.     if (settings["initrd"]:$[] != nil)
  161.         Initrd::Import (settings["initrd"]:$[]);
  162.     boolean ret = blImport (settings["specific"]:$[]);
  163.     BootCommon::write_settings = settings["write_settings"]:$[];
  164.     return ret;
  165.     }
  166.     /**
  167.       * Read settings from disk
  168.       * @return boolean true on success
  169.       */
  170.     global define boolean Read () {
  171.     y2milestone ("Reading configuration");
  172. // run Progress bar
  173.     list<string> stages = [
  174.         // progress stage, text in dialog (short, infinitiv)
  175.         _("Check boot loader"),
  176.         // progress stage, text in dialog (short, infinitiv)
  177.         _("Read partitioning"),
  178.         // progress stage, text in dialog (short, infinitiv)
  179.         _("Load boot loader settings"),
  180.     ];
  181.     list<string> titles = [
  182.         // progress step, text in dialog (short)
  183.         _("Checking boot loader..."),
  184.         // progress step, text in dialog (short)
  185.         _("Reading partitioning..."),
  186.         // progress step, text in dialog (short)
  187.         _("Loading boot loader settings..."),
  188.     ];
  189.     // dialog header
  190.     Progress::New (_("Initializing Boot Loader Configuration"),
  191.         " ", 3, stages, titles, "");
  192.  
  193.     Progress::NextStage ();
  194.     if (testAbort ())
  195.         return false;
  196.  
  197.     Bootloader::getLoaderType ();
  198.  
  199.     Progress::NextStage ();
  200.     if (testAbort ())
  201.         return false;
  202.  
  203.     BootCommon::DetectDisks ();
  204.         Progress::NextStage ();
  205.         if (testAbort ())
  206.             return false;
  207.  
  208.     boolean ret = blRead (true);
  209.     BootCommon::was_read = true;
  210.     old_vga = getKernelParam (getDefaultSection (), "vga");
  211.  
  212.     Progress::Finish ();
  213.     if (testAbort ())
  214.         return false;
  215.     y2debug ("Read settings: %1", Export ());
  216.     return ret;
  217.     }
  218.     /**
  219.       * Reset bootloader settings
  220.       * @param init boolean true if basic initialization of system-dependent
  221.       * settings should be done
  222.       */
  223.     global define void ResetEx (boolean init) {
  224.     if (Mode::autoinst ())
  225.         return;
  226.     y2milestone ("Reseting configuration");
  227.     BootCommon::was_proposed = false;
  228.     BootCommon::was_read = false;
  229.     BootCommon::loader_device = "";
  230. //    BootCommon::setLoaderType (nil);
  231.     BootCommon::changed = false;
  232.     BootCommon::location_changed = false;
  233. //    BootCommon::other_bl = $[];
  234.     BootCommon::files_edited = false;
  235.     BootCommon::write_settings = $[];
  236.     blReset (init);
  237.     }
  238.  
  239.     /**
  240.       * Reset bootloader settings
  241.       */
  242.     global define void Reset () {
  243.     return ResetEx (true);
  244.     }
  245.     /**
  246.       * Propose bootloader settings
  247.       */
  248.     global define void Propose () {
  249.     y2milestone ("Proposing configuration");
  250.     // have a current target map available in the log when we debug
  251.     y2debug ("Unfiltered target map: %1", (map<string,map>)Storage::GetTargetMap());
  252.     BootCommon::UpdateInstallationKernelParameters ();
  253.     blPropose ();
  254.     BootCommon::was_proposed = true;
  255.         BootCommon::changed = true;
  256.         BootCommon::location_changed = true;
  257.     BootCommon::partitioning_last_change = Storage::GetTargetChangeTime();
  258.     BootCommon::backup_mbr = true;
  259.     y2milestone ("Proposed settings: %1", Export ());
  260.     }
  261.     /**
  262.       * Display bootloader summary
  263.       * @return a list of summary lines
  264.       */
  265.     global define list<string> Summary () {
  266.     list<string> ret = blSummary ();
  267.     // check if default section was changed or not
  268.         string main_section = getProposedDefaultSection ();
  269.         if (main_section == nil)
  270.             return ret;
  271.     integer index = -1;
  272.     integer sectnum = -1;
  273.     if (getLoaderType () == "none")
  274.         return ret;
  275.         foreach (map<string,any> s, BootCommon::sections, {
  276.             index = index + 1;
  277.             if (s["name"]:"" == main_section)
  278.                 sectnum = index;
  279.         });
  280.         if (sectnum == -1)
  281.             return ret;
  282.     if (BootCommon::sections[sectnum, "__changed"]:false)
  283.         return ret;
  284.     string filtered_cmdline = filterchars (Kernel::GetCmdLine (),
  285.         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
  286.     if (size (filtered_cmdline) > 0)
  287.     {
  288.         ret = add (ret, sformat (
  289.         // part of summary, %1 is a part of kernel command line
  290.         _("Added Kernel Parameters: %1"),
  291.         Kernel::GetCmdLine ()));
  292.     }
  293.     return ret;
  294.     }
  295.  
  296.     /**
  297.       * Update read settings to new version of configuration files
  298.       */
  299.     global define void UpdateConfiguration () {
  300.     // first run bootloader-specific update function
  301.     blUpdate ();
  302.  
  303.     // remove ide-scsi emulation
  304.     list<string> parameters = listKernelParams ("LINUX_DEFAULT");
  305.     foreach (string p, parameters, {
  306.         if (regexpmatch (p, "^hd.=ide-scsi$")
  307.         || regexpmatch (p, "^hd.lun=.*$"))
  308.         {
  309.         string param = regexpsub (p, "^(.*)=.*$", "\\1");
  310.         setKernelParam ("LINUX_DEFAULT", param, nil);
  311.         }
  312.     });
  313.     // remove no more needed modules from MODULES_LOADED_ON_BOOT
  314.     string mlob = (string)
  315.         SCR::Read (.sysconfig.kernel.MODULES_LOADED_ON_BOOT);
  316.     list<string> mod_list = splitstring (mlob, " ");
  317.     mod_list = filter (string s, mod_list, ``(
  318.         s != "" && s != "cdrom" && s != "ide-cd" && s != "ide-scsi"
  319.     ));
  320.     mlob = mergestring (mod_list, " ");
  321.     SCR::Write (.sysconfig.kernel.MODULES_LOADED_ON_BOOT, mlob);
  322.     SCR::Write (.sysconfig.kernel, nil);
  323.     }
  324.  
  325.     /**
  326.      * Update the whole configuration
  327.      * @param iv a map representing the installed (original) version
  328.      * @param uv a map representing the version the system is upgraded to
  329.      * @return boolean true on success
  330.      */
  331.     global boolean Update (map<string,any> iv, map<string,any> uv) {
  332.         BootCommon::installed_version = iv;
  333.         BootCommon::update_version = uv;
  334.         return Write (); // write also reads the configuration and updates it
  335.     }
  336.  
  337.     /**
  338.      * Process update actions needed before packages update starts
  339.      */
  340.     global define void PreUpdate () {
  341.     y2milestone ("Running bootloader pre-update stuff");
  342.     }
  343.  
  344.     /**
  345.       * Write bootloader settings to disk
  346.       * @return boolean true on success
  347.       */
  348.     global define boolean Write () {
  349.     boolean ret = true;
  350.  
  351.     // proposing anything is irrelevant during update, this forces reading
  352.     // if settings weren't read before
  353.     if (Mode::update ())
  354.     {
  355.         BootCommon::was_proposed = false;
  356.         BootCommon::changed = true;
  357.         BootCommon::location_changed = true;
  358.         BootCommon::getLoaderType (! repeating_write);
  359.     }
  360.  
  361.     if (repeating_write)
  362.         BootCommon::was_read = true;
  363.     else
  364.         ReadOrProposeIfNeeded ();
  365.  
  366.     if (BootCommon::write_settings["save_all"]:false)
  367.         BootCommon::save_all = true;
  368.     if (BootCommon::save_all)
  369.     { // force saving everything
  370.         BootCommon::changed = true;
  371.         BootCommon::location_changed = true;
  372.         Initrd::changed = true;
  373.     }
  374.  
  375.     y2milestone ("Writing bootloader configuration");
  376.  
  377.     // run Progress bar
  378.         list<string> stages = [
  379.             // progress stage, text in dialog (short)
  380.             _("Create initrd"),
  381.             // progress stage, text in dialog (short)
  382.             _("Save boot loader configuration files"),
  383.             // progress stage, text in dialog (short)
  384.             _("Install boot loader"),
  385.         ];
  386.         list<string> titles = [
  387.             // progress step, text in dialog (short)
  388.             _("Creating initrd..."),
  389.             // progress step, text in dialog (short)
  390.             _("Saving boot loader configuration files..."),
  391.             // progress step, text in dialog (short)
  392.             _("Installing boot loader..."),
  393.         ];
  394.         // progress bar caption
  395.         if (Mode::normal ())
  396.     {
  397.         // progress line
  398.             Progress::New (_("Saving Boot Loader Configuration"),
  399.                 " ", 2, stages, titles, "");
  400.         Progress::NextStage ();
  401.     }
  402.         else
  403.         {
  404.             Progress::Title (titles[0]:"");
  405.         }
  406.  
  407.     map<string,any> params_to_save = $[];
  408.  
  409.     string new_vga = getKernelParam (getDefaultSection (), "vga");
  410.     if (new_vga != old_vga && new_vga != "false" && new_vga != "")
  411.     {
  412.         Initrd::setSplash (new_vga);
  413.         if (Stage::initial ())
  414.         params_to_save["vga"] = new_vga;
  415.     }
  416.  
  417.     // Initialize device mapper and LVM in target system
  418.     if (Stage::initial () || Mode::update ())
  419.     {
  420.         // FIXME: should be handled by partitioner
  421.         map out = (map)SCR::Execute (.target.bash_output,
  422.         "test -f /sbin/devmap_mknod.sh && /sbin/devmap_mknod.sh;" +
  423.         "test -f /sbin/vgscan && /sbin/vgscan --mknodes"
  424.         );
  425.         if (out["exit"]:0 != 0)
  426.         {
  427.         y2error ("Failed to initialize device mapper");
  428.         }
  429.         y2milestone ("Device mapper and LVM initialization output: %1", out);
  430.     }
  431.  
  432.     // save initrd
  433.     if ((Initrd::changed || ! Mode::normal ())
  434.         && ! (BootCommon::write_settings["forbid_save_initrd"]:false))
  435.     {
  436.         string vga = getKernelParam (getDefaultSection (), "vga");
  437.         if (vga != "false" && vga != "")
  438.         {
  439.         Initrd::setSplash (vga);
  440.         if (Stage::initial ())
  441.             params_to_save["vga"] = new_vga;
  442.         }
  443.         ret = Initrd::Write ();
  444.         BootCommon::changed = true;
  445.     }
  446.     if (! ret)
  447.         y2error ("Error occurred while creating initrd");
  448.  
  449.     if (Mode::commandline ())
  450.         BootCommon::changed = true;
  451.  
  452.     if (! (BootCommon::changed
  453.         || BootCommon::write_settings["initrd_changed_externally"]:false))
  454.     {
  455.         y2milestone ("No bootloader cfg. file saving needed, exiting");
  456. //        return true;
  457.     }
  458.  
  459.     if (Mode::normal ())
  460.         Progress::NextStage ();
  461.     else
  462.         {
  463.         if (! repeating_write)
  464.         Progress::NextStep ();
  465.             Progress::Title (titles[1]:"");
  466.         }
  467.  
  468.     // Write settings to /etc/sysconfig/bootloader
  469.     y2milestone ("Saving configuration files");
  470.     string lt = getLoaderType ();
  471.  
  472.         SCR::Write (.sysconfig.bootloader.LOADER_TYPE, lt);
  473. //        SCR::Write (.sysconfig.bootloader.LOADER_LOCATION,
  474. //            BootCommon::location);
  475. // FIXME
  476.     SCR::Write (.sysconfig.bootloader, nil);
  477.  
  478.     params_to_save["additional_failsafe_params"]
  479.         = BootCommon::GetAdditionalFailsafeParams ();
  480.     params_to_save["installation_kernel_params"] = Kernel::GetCmdLine ();
  481.     if (Stage::initial ())
  482.     {
  483.         SCR::Write (.target.ycp, "/var/lib/YaST2/bootloader.ycp",
  484.         params_to_save);
  485.     }
  486.  
  487.     if (getLoaderType () == "none")
  488.     {
  489.         return ret;
  490.     }
  491.  
  492.     // update graphics menu where possible
  493.     UpdateGfxMenu ();
  494.  
  495.     // save bootloader settings
  496.     boolean reinit = ! (Mode::update () || Mode::normal ());
  497.     y2milestone ("Reinitialize bootloader library before saving: %1",
  498.         reinit);
  499.     ret = blSave (true, reinit, true) && ret;
  500.     if (! ret)
  501.         y2error ("Error before configuration files saving finished");
  502.  
  503.         if (Mode::normal ())
  504.             Progress::NextStage ();
  505.         else
  506.         {
  507.         if (! repeating_write)
  508.         Progress::NextStep ();
  509.             Progress::Title (titles[2]:"");
  510.         }
  511.  
  512.     // call bootloader executable
  513.     y2milestone ("Calling bootloader executable");
  514.     ret = ret && blWrite ();
  515.  
  516.     if (! ret)
  517.     {
  518.         y2error ("Installing bootloader failed");
  519.         if (writeErrorPopup ())
  520.         {
  521.         repeating_write = true;
  522.         map res = (map)WFM::call( "bootloader_proposal", ["AskUser",
  523.             $[ "has_next": false]]);
  524.         if (res["workflow_sequence"]:nil == `next)
  525.         {
  526.             return Write ();
  527.         }
  528.         }
  529.     }
  530.     else
  531.     {
  532.     if (BootCommon::InstallingToFloppy ())
  533.     {
  534.         BootCommon::updateTimeoutPopupForFloppy
  535.         (BootCommon::getLoaderName (getLoaderType (), `summary));
  536.     }
  537.  
  538.  
  539.     }
  540.     return ret;
  541. }
  542.  
  543. // write mode settings function
  544.  
  545.     /**
  546.       * Set settings how to write bootloader
  547.       * @param settings map of settings
  548.       */
  549.     global define void SetWriteMode (map<string,any> settings) {
  550.     y2milestone ("Setting mode for writing: %1", settings);
  551.     foreach (string k, any v, settings, {
  552.         BootCommon::write_settings[k] = v;
  553.     });
  554.     }
  555.  
  556. // sections handling functions
  557.  
  558. /**
  559.   * Resolve a single symlink in key image_key in section map s
  560.   * @param section map map of section to change
  561.   * @param image_key string key in section that contains the link
  562.   * @return section map of the changed section
  563.   */
  564. global define map<string,any> ResolveSymlink(map<string,any> section, string key) {
  565.     // The "-m" is needed in case the link is an absolute link, so that it does
  566.     // not fail to resolve when the root partition is mounted in
  567.     // Installation::destdir.
  568.     string readlink_cmd = "/usr/bin/readlink -n -m " + Installation::destdir;
  569.     map out = $[];
  570.     string newval = "";
  571.  
  572.     // FIXME: find out why we need WFM::Execute() here (as olh used it above)
  573.     out = (map) WFM::Execute (.local.bash_output, readlink_cmd + section[key]:"");
  574.     if ( out["exit"]:0 == 0 && out["stdout"]:"" != "" ) {
  575.     newval = substring(out["stdout"]:"", size(Installation::destdir));
  576.     y2milestone("section %1: converting old %2 parameter from %3 to %4",
  577.         section["name"]:"", key, section[key]:"", newval);
  578.     section[key] = newval;
  579.     } else {
  580.     y2error ("section %1: failed to remap %2 parameter",
  581.         section["name"]:"", key);
  582.     }
  583.  
  584.     return section;
  585. //  y2milestone("old kernel parameter in section %1: %2", s["name"], s["kernel"]);
  586. //  s["kernel"] = SCR::Execute (.target.bash, "/usr/bin/readlink " + s["kernel"]);
  587. //  y2milestone("converted kernel parameter to: %2", s["kernel"]);
  588. }
  589.  
  590. /**
  591.   * Resolve symlinks in kernel and initrd paths, for existing linux, xen and
  592.   * failsafe sections
  593.   */
  594. // FIXME: this is the plan B solution, try to solve plan A in
  595. //        BootCommon.ycp:CreateLinuxSection() (line 435)
  596. global define void ResolveSymlinksInSections() {
  597.     list image_key_names = ["kernel", "image"];
  598.     string image_key_name = "";
  599.     integer i = 0;
  600.  
  601.     y2milestone("sections before remapping: %1", BootCommon::sections);
  602.  
  603.     // change only linux, failsafe and xen sections
  604.     BootCommon::sections = maplist (map<string,any> s, BootCommon::sections, {
  605.     // skip sections that are not linux, xen or failsafe
  606.     if ( !contains ( ["linux", "xen", "failsafe"] , s["original_name"]:"") ||
  607.          !contains ( ["image", "xen"] , s["type"]:"") ) {
  608.         y2milestone("section %1: not linux, xen or failsafe, skipping kernel and initrd remapping",
  609.         s["name"]:"");
  610.         return s;
  611.     }
  612.  
  613.     // first, resolve kernel link name
  614.     i = 0;
  615.     while ( i < size(image_key_names) ) {
  616.         image_key_name = image_key_names[i]:"";
  617.         // also skip sections that start with a grub device name
  618.         // "(hd0,7)/boot/vmlinuz", and are not on the default (currently
  619.         // mounted) boot partition
  620.         if ( haskey (s, image_key_name) ) {
  621.         if ( !regexpmatch(s[image_key_name]:"", "^\(hd.*\)") ) {
  622.             s = ResolveSymlink(s, image_key_name);
  623.         } else {
  624.             y2milestone("section %1: skipping remapping kernel symlink on other partition: %2",
  625.             s["name"]:"", s[image_key_name]:"");
  626.         }
  627.         }
  628.         i = i + 1;
  629.     }
  630.     // resolve initrd link name, but skip if it is on a non-default boot
  631.     // partition (see above)
  632.     if ( haskey (s, "initrd") ) {
  633.         if ( !regexpmatch(s["initrd"]:"", "^\(hd.*\)") ) {
  634.         s = ResolveSymlink(s, "initrd");
  635.         } else {
  636.         y2milestone("section %1: skipping remapping initrd symlink on other partition: %2",
  637.             s["name"]:"", s["initrd"]:"");
  638.         }
  639.     }
  640.     return s;
  641.     });
  642.  
  643.     y2milestone("sections after remapping: %1", BootCommon::sections);
  644. }
  645.  
  646.     /**
  647.       * return default section label
  648.       * @return string default section label
  649.       */
  650.     global define string getDefaultSection () {
  651.     ReadOrProposeIfNeeded ();
  652.     return BootCommon::globals["default"]:"";
  653.     }
  654.  
  655.     /**
  656.       * Get default section as proposed during installation
  657.       * @return section that was proposed as default during installation,
  658.       * if not known, return current default section if it is of type "image",
  659.       * if not found return first linux section, if no present, return empty
  660.       * string
  661.       */
  662.     global define string getProposedDefaultSection () {
  663.     ReadOrProposeIfNeeded ();
  664.     string defaultv = "";
  665.     string first_image = "";
  666.     string default_image = "";
  667.     foreach (map<string,any> s, BootCommon::sections, {
  668.         string title = s["name"]:"";
  669.         if (s["kernel"]:nil != nil)
  670.         {
  671.         if (first_image == "")
  672.             first_image = title;
  673.         if (title == getDefaultSection ())
  674.             default_image = title;
  675.         }
  676.         if (defaultv == "" && s["original_name"]:"" == "linux")
  677.         defaultv = title;
  678.     });
  679.     if (defaultv != "")
  680.         return defaultv;
  681.     if (default_image != "")
  682.         return default_image;
  683.     if (first_image != "")
  684.         return first_image;
  685.     return "";
  686.     }
  687.  
  688.     /**
  689.      * Add section for previous kernel and initrd (/boot/vmlinuz.previous,
  690.      * /boot/initrd.previous)
  691.      */
  692.     global define void AddPreviousSection () {
  693.     ReadOrProposeIfNeeded ();
  694.     // check if there is already present "Previous" section
  695.     BootCommon::sections = filter (map<string,any> s,BootCommon::sections,{
  696.         string title = s["name"]:"";
  697.         string type = s["original_name"]:"";
  698.         boolean preserve = type != "previous" && title != "previous"
  699.         && BootCommon::translateSectionTitle (title) != "previous";
  700.         return preserve;
  701.     });
  702.     // add the new section now
  703.     map<string,any> found_sect = nil;
  704.     string sect_name = getProposedDefaultSection ();
  705.     if (sect_name == "" || sect_name == nil)
  706.         return;
  707.  
  708.     foreach (map<string,any> s, BootCommon::sections, {
  709.         if (s["name"]:"" == sect_name)
  710.         found_sect = s;
  711.     });
  712.     if (found_sect == nil)
  713.         return;
  714.  
  715.     map<string,any> previous_section
  716.         = BootCommon::Linux2Previous (found_sect);
  717.     BootCommon::sections = add (BootCommon::sections, previous_section);
  718.     BootCommon::changed = true;
  719.     }
  720.  
  721.     /**
  722.       * get kernel parameters from bootloader configuration file
  723.       * @param section string section title, use DEFAULT for default section
  724.       * @param key string
  725.       * @return string value, "false" if not present,
  726.       * "true" if present key without value
  727.       */
  728.     global define string getKernelParam (string section, string key) {
  729.     ReadOrProposeIfNeeded ();
  730.     if (section == "DEFAULT")
  731.         section = getDefaultSection ();
  732.     else if (section == "LINUX_DEFAULT")
  733.         section = getProposedDefaultSection ();
  734.     if (section == nil)
  735.         return "";
  736.     map params = BootCommon::getKernelParamKeys ();
  737.     integer sectnum = -1;
  738.     integer index = -1;
  739.     foreach (map<string,any> s, BootCommon::sections, {
  740.         index = index + 1;
  741.         if (s["name"]:"" == section)
  742.         sectnum = index;
  743.     });
  744.     if (sectnum == -1)
  745.         return "";
  746.     string line = "";
  747.     if (contains (["root", "vga"], key))
  748.         return BootCommon::sections[sectnum, key]:"false";
  749.     else
  750.     {
  751.         line = BootCommon::sections[sectnum, "append"]:"";
  752.         return BootCommon::getKernelParamFromLine (line, key);
  753.     }
  754.     }
  755.  
  756.     /**
  757.       * List kernel parameters
  758.       * @param section string section title, use DEFAULT for default section
  759.       * @return a list of kernel parameters (in the form 'hdd=ide-scsi')
  760.       */
  761.     global define list<string> listKernelParams (string section) {
  762.     ReadOrProposeIfNeeded ();
  763.     if (section == "DEFAULT")
  764.         section = getDefaultSection ();
  765.     else if (section == "LINUX_DEFAULT")
  766.         section = getProposedDefaultSection ();
  767.     if (section == nil)
  768.         return [];
  769.     integer sectnum = -1;
  770.     integer index = -1;
  771.     foreach (map<string,any> s, BootCommon::sections, {
  772.         index = index + 1;
  773.         if (s["name"]:"" == section)
  774.         sectnum = index;
  775.     });
  776.     if (sectnum == -1)
  777.         return [];
  778.     string line = BootCommon::sections[sectnum, "append"]:"";
  779.         list<string> par = splitstring (line, " ");
  780.         par = filter (string p, par, ``(p != ""));
  781.     return par;
  782.     }
  783.  
  784.     /**
  785.       * Get list of bootloader sections
  786.       * @param type symbol what sections to be returned
  787.       *  `linux -> linux sections
  788.       *  `other -> other sections
  789.       *  `all   -> all sections
  790.       * @return list of strings representing sections names
  791.       */
  792.     global define list getSectionsList (symbol type) {
  793.     list<map<string,any> > sects = BootCommon::sections;
  794.     if (type == `other)
  795.     {
  796.         sects = filter (map<string,any> s, sects, ``(
  797.         ! haskey (s, "chainloader")
  798.         ));
  799.     }
  800.     else if (type == `linux)
  801.     {
  802.         sects = filter (map<string,any> s, sects, ``(
  803.         ! haskey (s, "kernel")));
  804.     }
  805.     list<string> sects_titles = maplist (map<string,any> s, sects, ``(
  806.         s["name"]:""));
  807.     sects_titles = filter (string s, sects_titles, ``(s != ""));
  808.     return sects_titles;
  809.     }
  810.  
  811.  
  812.     /**
  813.       * set kernel parameter to menu.lst
  814.       * @param section string section title, use DEFAULT for default section
  815.       * @param key string parameter key
  816.       * @param value string value, "false" to remove key,
  817.       *   "true" to add key without value
  818.       * @return boolean true on success
  819.       */
  820.     global define boolean setKernelParam
  821.     (string section, string key, string value)
  822.     {
  823.     if ((! Mode::config ()) && key == "vga" && (
  824.         Arch::s390 () || Arch::ppc ()
  825.     ))
  826.     {
  827.         y2warning ("Kernel of this architecture does not support the vga parameter");
  828.         return true;
  829.     }
  830.  
  831.     ReadOrProposeIfNeeded ();
  832.  
  833.     if (section == "DEFAULT")
  834.         section = getDefaultSection ();
  835.     else if (section == "LINUX_DEFAULT")
  836.         section = getProposedDefaultSection ();
  837.     if (section == nil)
  838.         return false;
  839.         integer sectnum = -1;
  840.         integer index = -1;
  841.         foreach (map<string,any> s, BootCommon::sections, {
  842.             index = index + 1;
  843.             if (s["name"]:"" == section)
  844.                 sectnum = index;
  845.         });
  846.         if (sectnum == -1)
  847.             return false;
  848.     string slabel = "";
  849.     if ((key == "vga" || key == "root") && (value == "true"))
  850.         return false;
  851.     if (contains (["root", "vga"], key))
  852.     {
  853.         if (value != "false")
  854.         {
  855.         BootCommon::sections[sectnum, key] = value;
  856.         }
  857.         else
  858.         {
  859.         BootCommon::sections[sectnum] = remove (
  860.             BootCommon::sections[sectnum]:$[], key);
  861.         }
  862.     }
  863.     else
  864.     {
  865.         string line = BootCommon::sections [sectnum, "append"]:"";
  866.         line = BootCommon::setKernelParamToLine (line, key, value);
  867.         BootCommon::sections [sectnum, "append"] = line;
  868.     }
  869.     BootCommon::changed = true;
  870.     boolean ret = true;
  871.     return ret;
  872.     }
  873.  
  874.     /**
  875.       * Get currently used bootloader, detect if not set yet
  876.       * @return string botloader type
  877.       */
  878.     global define string getLoaderType () {
  879.     return BootCommon::getLoaderType (false);
  880.     }
  881.  
  882.     /**
  883.       * Set type of bootloader
  884.       * Just a wrapper to BootCommon::setLoaderType
  885.       * @param bootloader string type of bootloader
  886.       */
  887.     global define void setLoaderType (string bootloader) {
  888.     BootCommon::setLoaderType (bootloader);
  889.     }
  890.  
  891.     /**
  892.       * Get root fs device
  893.       * @return string root device
  894.       */
  895.     global define string getRootDevice () {
  896.     ReadOrProposeIfNeeded ();
  897.     return BootCommon::RootPartitionDevice;
  898.     }
  899.  
  900.     /**
  901.       * Set root fs device
  902.       * @param device string root device
  903.       */
  904.     global define void setRootDevice (string device) {
  905.     ReadOrProposeIfNeeded ();
  906.     BootCommon::RootPartitionDevice = device;
  907.     }
  908.  
  909.     /**
  910.       * Get device containing /boot directory
  911.       * @return string boot device
  912.       */
  913.     global define string getBootDevice () {
  914.     ReadOrProposeIfNeeded ();
  915.     return BootCommon::BootPartitionDevice;
  916.     }
  917.  
  918.     /**
  919.       * Set device containing /boot directory
  920.       * @param device string boot device
  921.       */
  922.     global define void setBootDevice (string device) {
  923.     ReadOrProposeIfNeeded ();
  924.     BootCommon::BootPartitionDevice = device;
  925.     }
  926.  
  927.     /**
  928.       * Answer whether LBA is supported
  929.       * @return boolean true if supported
  930.       */
  931.     global define boolean LbaSupport() {
  932.     return BootCommon::LbaSupport ();
  933.     }
  934.  
  935.     /**
  936.       * Check whether settings were read or proposed, if not, decide
  937.       * what to do and read or propose settings
  938.       */
  939.     global define void ReadOrProposeIfNeeded () {
  940.         if (! (BootCommon::was_read || BootCommon::was_proposed))
  941.         {
  942.         y2milestone ("Stage::initial (): %1, update: %2, config: %3",
  943.         Stage::initial (), Mode::update (), Mode::config ());
  944.         if (Mode::config ())
  945.         {
  946.         y2milestone ("Not reading settings in Mode::config ()");
  947.         BootCommon::was_read = true;
  948.         BootCommon::was_proposed = true;
  949.         }
  950.         else if (Arch::ia64 () && Mode::update ()
  951. )// FIXME        && BootELILO::efi_layout_changed)
  952.         { // recreate config on IPF from scratch - request by rw
  953.         y2milestone ("Reproposing new configuration - IPF, EFI layout has changed");
  954.         Propose ();
  955.         }
  956.             else if (Stage::initial () && ! Mode::update ())
  957.             {
  958.                 Propose ();
  959.             }
  960.             else
  961.             {
  962.         boolean progress_orig = Progress::set (false);
  963.                 Read ();
  964.         Progress::set (progress_orig);
  965.         if (Mode::update ())
  966.         {
  967.             UpdateConfiguration ();
  968.             BootCommon::changed = true;
  969.             BootCommon::location_changed = true;
  970.         }
  971.             }
  972.         }
  973.     }
  974.  
  975.     /**
  976.      * Update the language of GFX menu according to currently selected language
  977.      * @return boolean true on success
  978.      */
  979.     global define boolean UpdateGfxMenu () {
  980.     if (getLoaderType () != "lilo" && getLoaderType () != "grub")
  981.         return true;
  982.  
  983.     boolean ret = BootCommon::UpdateGfxMenuContents ();
  984.     if (! Mode::normal ())
  985.         return true;
  986.     if (getLoaderType () == "lilo")
  987.     {
  988.       /*
  989.        * This is extreme boolshit, Bootloader::Library has to be called
  990.        */
  991.         string bl_command = "/sbin/lilo >> /var/log/YaST2/y2log_bootloader 2>&1";
  992.         boolean command_ret = 0 == SCR::Execute (.target.bash, bl_command);
  993.         if (! command_ret)
  994.         {
  995.         y2error ("Execution of installation command failed");
  996.         return false;
  997.         }
  998.     }
  999.     return ret;
  1000.     }
  1001.  
  1002. }
  1003.