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 / BootCommon.ycp < prev    next >
Text File  |  2006-11-29  |  25KB  |  941 lines

  1. /**
  2.  * File:
  3.  *      modules/BootCommon.ycp
  4.  *
  5.  * Module:
  6.  *      Bootloader installation and configuration
  7.  *
  8.  * Summary:
  9.  *      Data to be shared between common and bootloader-specific parts of
  10.  *      bootloader configurator/installator, generic versions of bootloader
  11.  *      specific functions
  12.  *
  13.  * Authors:
  14.  *      Jiri Srain <jsrain@suse.cz>
  15.  *      Joachim Plack <jplack@suse.de>
  16.  *      Olaf Dabrunz <od@suse.de>
  17.  *
  18.  * $Id: BootCommon.ycp 34587 2006-11-24 16:02:55Z odabrunz $
  19.  *
  20.  */
  21.  
  22. {
  23. module "BootCommon";
  24.  
  25. textdomain "bootloader";
  26.  
  27. import "Arch";
  28. import "GfxMenu";
  29. import "HTML";
  30. import "Mode";
  31. import "PackageSystem";
  32. import "Storage";
  33. import "String";
  34. import "Pkg";
  35.  
  36.  
  37. // General bootloader settings
  38.  
  39. /**
  40.  * map of global options and types for new perl-Bootloader interface
  41.  */
  42. global map<string,any> global_options = $[];
  43.  
  44. /**
  45.  * map of section options and types for new perl-Bootloader interface
  46.  */
  47. global map<string,any> section_options = $[];
  48.  
  49. /**
  50.  * map of other exported information for new perl-Bootloader interface
  51.  */
  52. global map<string,any> exports = $[];
  53.  
  54. /**
  55.  * map of global options and values
  56.  */
  57. global map<string,string> globals = $[];
  58.  
  59. /**
  60.  * list of section
  61.  */
  62. global list<map<string,any> > sections = [];
  63.  
  64. /**
  65.  * device mapping between Linux and firmware
  66.  */
  67. global map<string,string> device_mapping = $[];
  68.  
  69. /**
  70.  * device to save loader stage 1 to
  71.  */
  72. // FIXME: what is this variable needed for
  73. global string loader_device = nil;
  74.  
  75. /**
  76.  * Embed stage 1.5 of the bootloader to dedicated area (if supported)?
  77.  * This is currently only supported by GRUB. A stage 1.5 can be put into the
  78.  * area after the MBR (into the rest of the very first cylinder) or into the
  79.  * "boot loader area" of some filesystems such as FFS and ReiserFS. For more
  80.  * information, see the grub documentation, esp.
  81.  *    "info '(grub.info.gz)Bootstrap tricks'"
  82.  *    "info '(grub.info.gz)Images'"
  83.  */
  84. // This needs to be defined here so that various files can include it.
  85. // BootCommon.ycp is currently the only central include file, separate include
  86. // files that are central and specific to each bootloader do not exist (yet?).
  87. global boolean embed_stage15 = true;
  88.  
  89.  
  90.  
  91. // proposal helping variables
  92.  
  93. /**
  94.  * The kind of bootloader location that the user selected last time he went to
  95.  * the dialog. Used to as a hint next time a proposal is requested, so the
  96.  * proposal can try to satisfy the user's previous preference.
  97.  * Currently, valid values are: mbr, boot, root, floppy, mbr_md, none
  98.  */
  99. global string selected_location = nil;
  100.  
  101.  
  102.  
  103. /* These global variables and functions are needed in included files */
  104.  
  105. /**
  106.   * string sepresenting device name of /boot partition
  107.   * same as RootPartitionDevice if no separate /boot partition
  108.   */
  109. global string BootPartitionDevice = "";
  110.  
  111. /**
  112.   * string representing device name of / partition
  113.   */
  114. global string RootPartitionDevice = "";
  115.  
  116. /**
  117.   * Parameters of currently used bootloader
  118.   */
  119. global map<string, any> current_bootloader_attribs = $[];
  120.  
  121. /**
  122.   * Parameters of all bootloaders
  123.   */
  124. global map<string,map<string, any> > bootloader_attribs = $[];
  125.  
  126. /**
  127.   * Name of currently edited section
  128.   */
  129. global string current_section_name = nil;
  130.  
  131. /**
  132.  * Index of current section, -1 for new created section
  133.  */
  134. global integer current_section_index = -1;
  135.  
  136. /**
  137.   * Curtrently edited section -- tmp store
  138.   */
  139. global map<string,any> current_section = $[];
  140.  
  141.  
  142. /**
  143.   * list of installed floppy devices
  144.   */
  145. global list<string> floppy_devices = nil;
  146.  
  147. /**
  148.   * Option types for different bootloaders
  149.   */
  150. global map<string,map<string,string> > opt_types = $[];
  151.  
  152. /**
  153.   * device holding MBR for bootloader
  154.   */
  155. global string mbrDisk = "";
  156.  
  157. /**
  158.   * was currently edited section changed (== true)
  159.   */
  160. global boolean one_section_changed = false;
  161.  
  162. /**
  163.   * Backup original MBR before installing bootloader
  164.   */
  165. global boolean backup_mbr = false;
  166.  
  167. /**
  168.   * Activate bootloader partition during installation?
  169.   */
  170. global boolean activate = false;
  171.  
  172. /**
  173.   * Replace MBR with generic code after bootloader installation?
  174.   */
  175. global boolean repl_mbr = false;
  176.  
  177. /**
  178.   * Kernel parameters at previous detection
  179.   */
  180. global string kernelCmdLine = "";
  181.  
  182. /**
  183.   * were settings changed (== true)
  184.   */
  185. global boolean changed = false;
  186.  
  187.  
  188. global map<string,any> installed_version = $[];
  189. global map<string,any> update_version = $[];
  190.  
  191. global map<string,string> edited_files = $[];
  192. // common variables
  193.  
  194. /**
  195.   * type of bootloader to configure/being configured
  196.   * shall be one of "lilo", "grub", "silo", "milo", "aboot",
  197.   * "elilo", "ppc", "zipl", "mips"
  198.   */
  199. string loader_type = nil;
  200.  
  201. // sysconfig variables
  202.  
  203. // installation proposal help variables
  204.  
  205. /**
  206.   * Last detection proposed to prefer lilo instead of grub
  207.   */
  208. global boolean prefer_lilo = false;
  209.  
  210. /**
  211.   * List of partitions deleted in primary proposal
  212.   */
  213. global list<string> del_parts = [];
  214.  
  215. // variables for storing data
  216.  
  217. // saving mode setting functions
  218.  
  219. /**
  220.   * map of save mode settings
  221.   */
  222. global map write_settings = $[];
  223.  
  224. // summary dialog state
  225.  
  226. /**
  227.   * Show verbose summary output
  228.   */
  229. global boolean verbose = false;
  230.  
  231. // ui help variables
  232.  
  233.  
  234. string additional_failsafe_params = "";
  235.  
  236.  
  237. // other variables
  238.  
  239. /**
  240.   * Settings of other bootloaders used when switching bootloader
  241.   */
  242. global map other_bl = $[];
  243.  
  244. // bootloader installation variables
  245.  
  246. /**
  247.   * Was the activate flag changed by user?
  248.   */
  249. global boolean activate_changed = false;
  250. /**
  251.   * Save everything, not only changed settings
  252.   */
  253. global boolean save_all = false;
  254.  
  255. // state variables
  256.  
  257. /**
  258.   * was the propose function called (== true)
  259.   */
  260. global boolean was_proposed = false;
  261. /**
  262.   * Were module settings read (== true)
  263.   */
  264. global boolean was_read = false;
  265. /**
  266.   * were sections settings changes (== true)
  267.   */
  268. global boolean sections_changed = false;
  269. /**
  270.   * Was bootloader location changed? (== true)
  271.   */
  272. global boolean location_changed = false;
  273. /**
  274.   * Were configuration files manually edited and chamged?
  275.   */
  276. global boolean files_edited = false;
  277. /**
  278.   * Has been files edited warning already shown?
  279.   */
  280. global boolean files_edited_warned = false;
  281. /**
  282.   * Shall be settings saved when finishing bootloader configuration?
  283.   */
  284. global boolean save_on_finish = true;
  285. /**
  286.   * time of last change of partitioning
  287.   */
  288. global integer partitioning_last_change = 0;
  289. /**
  290.  * true if memtest was removed by user (manually) during the installation
  291.  * proposal
  292.  */
  293. global list<string> removed_sections = [];
  294.  
  295. /**
  296.  * The name of the default section as it was read
  297.  */
  298. global string read_default_section_name = "";
  299.  
  300. /**
  301.  * Types of sections that should be updated (changed device names)
  302.  */
  303. global list<string> update_section_types
  304.     = [ "linux", "failsafe", "initrd", "floppy" ];
  305.  
  306.  
  307.  
  308. global define string getLoaderType (boolean recheck);
  309. global define list<string> getBootloaders ();
  310. global define list<string> Summary ();
  311. global define boolean UsingXenPae();
  312.  
  313.  
  314. //
  315. // FIXME: the select and selectdevice seem to be broken: the default value of
  316. // the widget description string needs to be patched with the current value of
  317. // the widget
  318. //
  319. global void change_widget_default_value (string itemname, string defaultvalue) {
  320.     // Put defaultvalue as default value into widget description item like
  321.     // "boot_{chrp,prep,iseries,...}_custom" or "boot_custom".
  322.     // Examples:
  323.     // "select:PReP or FAT partition::/dev/sda1:/dev/sda3:/dev/sdb1:/dev/sdd1" ->
  324.     // "select:PReP or FAT partition:/dev/sda3:/dev/sda1:/dev/sda3:/dev/sdb1:/dev/sdd1"
  325.     //
  326.     // "selectdevice:Custom Boot Partition::/dev/sda3" ->
  327.     // "selectdevice:Custom Boot Partition:/dev/sda3:/dev/sda3"
  328.     string old_description = global_options[itemname]:"";
  329.     global_options[itemname] =
  330.     regexpsub( old_description, "^([^:]*:[^:]*:).*$", "\\1") +
  331.     defaultvalue +
  332.     regexpsub( old_description, "^[^:]*:[^:]*:[^:]*(:.*)$", "\\1");
  333. }
  334.  
  335.  
  336. /*
  337.  * help message and dscription definitions
  338.  */
  339. include "bootloader/generic/helps.ycp";
  340.  
  341. include "bootloader/routines/popups.ycp";
  342. include "bootloader/routines/misc.ycp";
  343. // FIXME: there are other archs than i386, this is not 'commmon'
  344. include "bootloader/routines/lilolike.ycp";
  345. include "bootloader/routines/lib_iface.ycp";
  346.  
  347.  
  348.  
  349. // interface to bootloader library
  350.  
  351.  
  352.  
  353.  
  354. // FIXME 2x functions should not be finally here...
  355. /**
  356.  * Check whether XEN is selected for installation resp. selected
  357.  * @return boolean true of XEN installed/selected
  358.  */
  359. global boolean XenPresent () {
  360.     return (! contains (removed_sections, "xen"))
  361.     && (Mode::test ()
  362.         || (Mode::normal () && Pkg::IsProvided ("xen")
  363.         && Pkg::IsProvided ("kernel-xen"))
  364.         || (! Mode::normal () && Pkg::IsSelected ("xen")
  365.         && Pkg::IsSelected ("kernel-xen"))
  366.         || UsingXenPae());
  367. }
  368.  
  369. global boolean UsingXenPae() {
  370.     if (Mode::test())
  371.     return true;
  372.     if (Mode::normal())
  373.         return Pkg::IsProvided ("kernel-xenpae");
  374.     return Pkg::IsSelected ("kernel-xenpae");
  375. }
  376.  
  377. /**
  378.  * Get the size of memory for XEN's domain 0
  379.  * @return the memory size in kB
  380.  */
  381. global integer Dom0MemorySize () {
  382.     list<map> memory = (list<map>) SCR::Read(.probe.memory);
  383.  
  384.     y2milestone("memory: %1", memory);
  385.     integer memory_size = 0;
  386.  
  387.     foreach(map info, memory, {
  388.             // internal class, main memory
  389.             if (info["class_id"]:0 == 257 && info["sub_class_id"]:0 == 2)
  390.             {
  391.                 list<map> minf = info["resource", "phys_mem"]:[];
  392.                 foreach(map i, minf, {
  393.                         memory_size = memory_size + i["range"]:0;
  394.                     }
  395.                 );
  396.             }
  397.         }
  398.     );
  399.     // size in kB lowered 64 MB for XEN itself
  400.     memory_size = memory_size / 1024 - (64 * 1024);
  401.     y2milestone ("Memory size for XEN domain 0: %1", memory_size);
  402.     return memory_size;
  403. }
  404.  
  405.  
  406. /**
  407.  * Create section for linux kernel
  408.  * @param title string the section name to create (untranslated)
  409.  * @return a map describing the section
  410.  */
  411. global map<string,any> CreateLinuxSection (string title) {
  412.     if (title == "memtest86")
  413.     {
  414.     if (MemtestPresent ())
  415.     {
  416.         return $[
  417.         "name" : translateSectionTitle (title),
  418.         "original_name" : title,
  419.         "type" : "image",
  420.         "kernel" : "/boot/memtest.bin",
  421.         "__auto" : true,
  422.         "__changed" : false,
  423.         "__devs" : [BootCommon::BootPartitionDevice],
  424.         ];
  425.     }
  426.     else
  427.     {
  428.         return $[];
  429.     }
  430.     }
  431.     string resume = BootArch::ResumeAvailable ()
  432.     ? getLargestSwapPartition ()
  433.     : "";
  434.  
  435.     // FIXME:
  436.     // This only works in the installed system (problem with GetFinalKernel))),
  437.     // in all other cases we use the symlinks.
  438.  
  439.     string kernel_fn = "";
  440.     string initrd_fn = "";
  441.  
  442.     if (Mode::normal ()) {
  443.     // Find out the file names of the "real" kernel and initrd files, with
  444.     // version etc. pp. whatever (currently version-flavor) attached.
  445.     // FIXME: also do this for xen and xenpae kernels as found below
  446.     //
  447.     // First, get the file names in the "selected" kernel package,
  448.     string kernel_package = Kernel::GetFinalKernel();
  449.     list<string> files = Pkg::PkgGetFilelist( kernel_package, `any );
  450.     y2milestone ("kernel package %1 has these files: %2", kernel_package, files);
  451.  
  452.     // then find the first file that matches the arch-dependent kernel file
  453.     // name prefix and the initrd filename prefix.
  454.     string kernel_prefix = "/boot/" + Kernel::GetBinary ();
  455.     string initrd_prefix = "/boot/initrd";
  456.  
  457.     list<string> files_filtered = filter (string file, files, {
  458.         return ( substring(file, 0, size(kernel_prefix)) == kernel_prefix );
  459.     });
  460.     kernel_fn = (
  461.         title == "wildcard" ?
  462.         "/boot/" + Kernel::GetBinary () + "-*" :
  463.         files_filtered[0]:""
  464.     );
  465.  
  466.     files_filtered = filter (string file, files, {
  467.         return substring(file, 0, size(initrd_prefix)) == initrd_prefix ;
  468.     });
  469.     initrd_fn = (
  470.         title == "wildcard" ?
  471.         "/boot/initrd-*" :
  472.         files_filtered[0]:""
  473.     );
  474.     } else {
  475.     kernel_fn = "/boot/" + Kernel::GetBinary ()
  476.         + (title == "wildcard" ? "-*" : "");
  477.     initrd_fn = "/boot/initrd" + (title == "wildcard" ? "-*" : "");
  478.     }
  479.     // done: kernel_fn and initrd_fn are the results
  480.     y2milestone ("kernel_fn: %1 initrd_fn: %2", kernel_fn, initrd_fn);
  481.  
  482.     map<string,any> ret = $[
  483.     "name" : translateSectionTitle (title),
  484.     "original_name" : title,
  485.     "type" : "image",
  486.     "kernel" : kernel_fn,
  487.     "initrd" : initrd_fn,
  488.     "root" : RootPartitionDevice,
  489.     "append" : (title == "failsafe")
  490.         ? BootArch::FailsafeKernelParams ()
  491.         : BootArch::DefaultKernelParams (resume),
  492.     "__auto" : true,
  493.     "__changed" : false,
  494.     "__devs" : [BootPartitionDevice, RootPartitionDevice],
  495.     ];
  496.     if (BootArch::VgaAvailable () && Kernel::GetVgaType () != "")
  497.     {
  498.     if (title == "failsafe")
  499.         ret["vga"] = "normal";
  500.     else
  501.         ret["vga"] = Kernel::GetVgaType ();
  502.     }
  503.     if (title == "xen")
  504.     {
  505.         ret["type"] = "xen";
  506.     ret["xen_append"] = "";
  507.         if (UsingXenPae()) {
  508.         ret["xen"] = "/boot/xen-pae.gz";
  509.         ret["kernel"] = "/boot/" + Kernel::GetBinary () + "-xenpae";
  510.         ret["initrd"] = "/boot/initrd-xenpae";
  511.     } else {
  512.         ret["xen"] = "/boot/xen.gz";
  513.         ret["kernel"] = "/boot/" + Kernel::GetBinary () + "-xen";
  514.         ret["initrd"] = "/boot/initrd-xen";
  515.     }
  516.     }
  517.     else if (title == "wildcard")
  518.     {
  519.     ret["wildcard"] = kernel_fn;
  520.     ret["name"] = "*";
  521.     }
  522.     return ret;
  523. }
  524.  
  525. // generic versions of bootloader-specific functions
  526.  
  527. /**
  528.   * Export bootloader settings to a map
  529.   * @return bootloader settings
  530.   */
  531. global define map Export () {
  532.     map exp = $[
  533.     "global": globals,
  534.     "sections" : sections,
  535.     "repl_mbr" : repl_mbr,
  536.     "activate" : activate,
  537.     "device_map" : device_mapping,
  538.     ];
  539.     return exp;
  540. }
  541.  
  542. /**
  543.   * Import settings from a map
  544.   * @param settings map of bootloader settings
  545.   * @return boolean true on success
  546.   */
  547. global define boolean Import (map settings) {
  548.     globals = settings["global"]:$[];
  549.     sections = settings["sections"]:[];
  550.     repl_mbr = settings["repl_mbr"]:false;
  551.     activate = settings["activate"]:false;
  552.     device_mapping = settings["device_map"]:$[];
  553.     return true;
  554. }
  555.  
  556. /**
  557.  * Read settings from disk
  558.  * @param reread boolean true to force reread settings from system
  559.  * @return boolean true on success
  560.  */
  561. global boolean Read (boolean reread) {
  562.     string bl = getLoaderType (false);
  563.     if (bl == "none")
  564.     return true;
  565.     InitializeLibrary (reread, bl);
  566.     if (reread)
  567.     {
  568.     BootCommon::ReadFiles ();
  569.     }
  570.     sections = GetSections ();
  571.     globals = GetGlobal ();
  572.     device_mapping = GetDeviceMap ();
  573.     read_default_section_name = "";
  574.     foreach (map<string,any> s, sections, {
  575.     if (s["original_name"]:"" == "linux"
  576.         && read_default_section_name == "")
  577.     {
  578.         read_default_section_name = s["name"]:"";
  579.     }
  580.     });
  581.  
  582.     // convert root device names in sections to kernel device names, if
  583.     // possible
  584.     sections = maplist (map<string,any> s, sections, {
  585.     s["root"] = BootCommon::MountByDev2Dev(s["root"]:"");
  586.     return s;
  587.     });
  588.  
  589.     return true;
  590. }
  591.  
  592. /**
  593.   * Reset bootloader settings
  594.   * @param init boolean true to repropose also device map
  595.   */
  596. global define void Reset (boolean init) {
  597.     sections = [];
  598.     globals = $[];
  599.     // DetectDisks ();
  600.     repl_mbr = false;
  601.     activate = false;
  602.     activate_changed = false;
  603.     removed_sections = [];
  604.     was_proposed = false;
  605.     if (init)
  606.     {
  607.     ProposeDeviceMap ();
  608.     }
  609. }
  610.  
  611. /**
  612.  * Propose bootloader settings
  613.  */
  614. global void Propose () {
  615.     y2error ("No generic propose function available");
  616. }
  617.  
  618. /**
  619.  * Save all bootloader configuration files to the cache of the PlugLib
  620.  * PlugLib must be initialized properly !!!
  621.  * @param clean boolean true if settings should be cleaned up (checking their
  622.  *  correctness, supposing all files are on the disk)
  623.  * @param init boolean true to init the library
  624.  * @param flush boolean true to flush settings to the disk
  625.  * @return boolean true if success
  626.  */
  627. global boolean Save (boolean clean, boolean init, boolean flush) {
  628.     if (clean)
  629.     {
  630.     BootCommon::RemoveUnexistentSections ("", "");
  631.     // BootCommon::UpdateInitrdLine ();
  632.     BootCommon::UpdateAppend ();
  633.     BootCommon::UpdateGfxMenu ();
  634.     }
  635.     boolean ret = true;
  636.     string bl = getLoaderType (false);
  637.     if (bl == "none")
  638.     return true;
  639.  
  640.     InitializeLibrary (init, bl);
  641.  
  642.     list<map<string,string> > sects = maplist (map<string,any> s, sections, {
  643.     return (map<string,string>)
  644.         filter (string k, any v, s, { return is (v, string); });
  645.     });
  646.  
  647.     // convert root device names in sections to the device names indicated by
  648.     // "mountby"
  649.     sects = maplist (map<string,string> s, sects, {
  650.     s["root"] = BootCommon::Dev2MountByDev(s["root"]:"");
  651.     return s;
  652.     });
  653.  
  654.     ret = ret && SetDeviceMap (device_mapping);
  655.     ret = ret && SetSections (sects);
  656.     ret = ret && SetGlobal (globals);
  657.     if (flush)
  658.     {
  659.     ret = ret && CommitSettings ();
  660.     }
  661.     return ret;
  662. }
  663.     /**
  664.       * Display bootloader summary
  665.       * @return a list of summary lines
  666.       */
  667.     global define list<string> Summary () {
  668.     if (getLoaderType (false) == "none")
  669.     {
  670.         return [HTML::Colorize (
  671.         getLoaderName (getLoaderType (false), `summary),
  672.         "red") ];
  673.     }
  674.     map targetMap = Storage::GetTargetMap ();
  675.     map boot_target = targetMap[loader_device]:$[];
  676.     string target_name = "";
  677.     if (boot_target == $[])
  678.     {
  679.         target_name = loader_device;
  680.         if (target_name == "mbr_md")
  681.         {
  682.         list<string> mbrs = maplist (string d, integer id,
  683.             Md2Partitions (BootPartitionDevice),
  684.         {
  685.             map p_dev = Storage::GetDiskPartition (d);
  686.             return p_dev["disk"]:"";
  687.         });
  688.         // summary part, %1 is a list of device names
  689.         target_name = sformat (_("Master boot records of disks %1"),
  690.             mergestring (mbrs, ", "));
  691.         }
  692.     }
  693.     else
  694.     {
  695.         target_name = boot_target["name"]:"disk";
  696.     }
  697.     target_name = AddMbrToDescription (target_name, loader_device);
  698.  
  699.     list<string> result = [];
  700.     // summary text, %1 is bootloader name (eg. LILO)
  701.     result = add (result, sformat (_("Boot Loader Type: %1"),
  702.         getLoaderName (getLoaderType (false), `summary)));
  703.     // summary text, location is location description (eg. /dev/hda)
  704.     result = add (result, sformat (_("Location: %1"), target_name));
  705.     list<string> sects = [];
  706.     foreach (map<string,any> s, sections, {
  707.         string title = s["name"]:"";
  708.         // section name "suffix" for default section
  709.         string def = title == globals["default"]:"" ? _(" (default)") : "";
  710.         sects = add (sects, sformat ("%1%2", title, def));
  711.     });
  712.     // summary text. %1 is list of bootloader sections
  713.     result = add (result, sformat (_("Sections: %1"),
  714.         String::EscapeTags (mergestring (sects, ", "))));
  715.     if (loader_device == "/dev/null")
  716.         // summary text
  717.         result = add (result, _("Do not install boot loader; just create
  718. configuration files"));
  719.     return result;
  720.     }
  721.  
  722.     /**
  723.       * Update read settings to new version of configuration files
  724.       */
  725.     global define void Update () {
  726.     y2debug ("No generic update function available");
  727.     }
  728.  
  729. /**
  730.  * Write bootloader settings to disk
  731.  * @return boolean true on success
  732.  */
  733. global define boolean Write () {
  734.     y2error ("No generic write function available");
  735.     return false;
  736. }
  737.  
  738.  
  739. // end of generic versions of bootloader-specific functions
  740. //-----------------------------------------------------------------------------
  741. // common functions start
  742.  
  743. // bootloader type handling functions
  744.  
  745. /**
  746.   * Set attributes of specified bootloader to variable containing
  747.   * attributes of currently used bootloader, call its initializer
  748.   * @param loader_type string loader type to initialize
  749.   */
  750. global define void setCurrentLoaderAttribs (string loader_type) {
  751.     y2milestone ("Setting attributes for bootloader %1", loader_type);
  752.     // testsuite hack
  753.     if (Mode::test ())
  754.         return;
  755.     if (loader_type == nil)
  756.     {
  757.     y2error ("Setting loader type to nil, this is wrong");
  758.     return;
  759.     }
  760.  
  761.     // FIXME: this should be blInitializer in switcher.ycp for code cleanness
  762.     // and understandability
  763.     if (bootloader_attribs[loader_type, "initializer"]:nil != nil)
  764.     {
  765.     y2milestone ("Running bootloader initializer");
  766.     void () toEval = (void ()) (bootloader_attribs[loader_type, "initializer"]:nil);
  767.     toEval ();
  768.     y2milestone ("Initializer finished");
  769.     }
  770.     else
  771.     {
  772.     y2error ("No initializer found for >>%1<<", loader_type);
  773.     current_bootloader_attribs = $[];
  774.     }
  775.  
  776.     current_bootloader_attribs = (map<string, any>) union (
  777.     current_bootloader_attribs,
  778.     (map<string, any>) eval (bootloader_attribs[loader_type]:$[])
  779.     );
  780. }
  781.  
  782. /**
  783.  * Check whether loader with specified name is supported
  784.  * @param loader string name of loader to check
  785.  * @return string the loader name if supported, "none" otherwise
  786.  */
  787. string SupportedLoader (string loader) {
  788.     if (contains (["grub", "lilo", "zipl", "ppc", "elilo"], loader))
  789.     return loader;
  790.     return "none";
  791. }
  792.  
  793. /**
  794.   * Get currently used bootloader, detect if not set yet
  795.   * @param recheck boolean force checking bootloader
  796.   * @return string botloader type
  797.   */
  798. global define string getLoaderType (boolean recheck) {
  799.     if ((! recheck) && (loader_type != nil))
  800.         return loader_type;
  801.     // read bootloader to use from disk
  802.     if (Mode::update () || Mode::normal () || Mode::repair ())
  803.     {
  804.     loader_type = (string)SCR::Read (.sysconfig.bootloader.LOADER_TYPE);
  805.     if (loader_type != nil && loader_type != "")
  806.     {
  807.         if (loader_type == "s390")
  808.             loader_type = "zipl";
  809.         if (loader_type == "lilo" && Arch::ppc ())
  810.             loader_type = "ppc";
  811.         y2milestone ("Sysconfig bootloader is %1, using", loader_type);
  812.         loader_type = SupportedLoader (loader_type);
  813.         y2milestone ("Sysconfig bootloader is %1, using", loader_type);
  814.         setCurrentLoaderAttribs (loader_type);
  815.         return loader_type;
  816.     }
  817.     if (Mode::update ())
  818.     {
  819.       // FIXME: this is extremely broken, no arch specifica here !!
  820.         if (Arch::i386 ())
  821.         { 
  822.         // no sysconfig variable -> old version installed -> use LILO
  823.         loader_type = "lilo";
  824.         loader_type = SupportedLoader (loader_type);
  825.         setCurrentLoaderAttribs (loader_type);
  826.         return loader_type;
  827.         }
  828.     }
  829.     }
  830.     // detect bootloader
  831.     loader_type = (string)SCR::Read (.probe.boot_arch);
  832.     if (loader_type == "s390")
  833.       loader_type = "zipl";
  834.     y2milestone ("Bootloader detection returned %1", loader_type);
  835.     if (Arch::is_uml ())
  836.     {
  837.     y2milestone ("Not installing any bootloader for UML");
  838.     loader_type = "none";
  839.     }
  840.     if (loader_type == "grub" && Storage::UseLilo())
  841.     {
  842.     loader_type = "lilo";
  843.     prefer_lilo = true;
  844.     }
  845.     else
  846.     {
  847.         prefer_lilo = false;
  848.     }
  849.  
  850.     loader_type = SupportedLoader (loader_type);
  851.     y2milestone ("Detected bootloader %1", loader_type);
  852.     setCurrentLoaderAttribs (loader_type);
  853.     return loader_type;
  854. }
  855.  
  856. /**
  857.   * set type of bootloader
  858.   * @param bootloader string type of bootloader
  859.   */
  860. global define void setLoaderType (string bootloader) {
  861.     if (bootloader == nil)
  862.     {
  863.         y2milestone ("Resetting the loader type");
  864.         loader_type = nil;
  865.     }
  866.     y2milestone ("Setting bootloader to >>%1<<", bootloader);
  867.     if (bootloader != nil
  868.         && contains(bootloaders, bootloader)
  869.         && ! Mode::test ())
  870.     {
  871.         // don't configure package maneger during autoinstallation preparing
  872.         if (Mode::normal () && (! (Mode::config () || Mode::repair ())))
  873.         {
  874.         PackageSystem::InstallAll (getBootloaderPackages (bootloader));
  875.         }
  876.         else if (Stage::initial () && (! (Mode::repair ())))
  877.         {
  878.         boolean pkg_added = false;
  879.         foreach (string p, getBootloaderPackages (bootloader), {
  880.             if (! Pkg::IsSelected (p))
  881.         {
  882.             Pkg::PkgInstall (bootloader);
  883.             pkg_added = true;
  884.         }
  885.         });
  886.         if (pkg_added)
  887.         {
  888.         // if package was added in inst. proposal, I can't be sure
  889.         // that dependencies will be solved
  890.         Pkg::PkgSolve (false);
  891.         }
  892.         }
  893.     }
  894.     else if (! Mode::test ())
  895.     {
  896.         y2error ("Unknown bootloader");
  897.     }
  898.     loader_type = bootloader;
  899.     if (loader_type != nil)
  900.         setCurrentLoaderAttribs (loader_type);
  901.     y2milestone ("Loader type set");
  902. }
  903.  
  904. /**
  905.   * List bootloaders available for configured architecture
  906.   * @return a list of bootloaders
  907.   */
  908. global define list<string> getBootloaders () {
  909.     if (Mode::config ())
  910.     {
  911.         return ["grub", "lilo", "elilo", "zipl", "ppc", "default", "none"];
  912.     }
  913.     list<string> ret = [
  914.     getLoaderType (false),
  915.     (string)SCR::Read (.probe.boot_arch)
  916.     ];
  917.     if (Arch::i386 () || Arch::x86_64 ())
  918.     {
  919.         ret = (list<string>)merge (ret, ["lilo", "grub"]);
  920.     }
  921.     // in order not to display it twice when "none" is selected
  922.     ret = filter (string l, ret, {
  923.       return l != "none";
  924.     });
  925.     ret = toset (ret);
  926.     ret = add (ret, "none");
  927.     return ret;
  928. }
  929.  
  930. }
  931.  
  932. /*
  933.  * Local variables:
  934.  *     mode: ycp
  935.  *     mode: font-lock
  936.  *     mode: auto-fill
  937.  *     indent-level: 4
  938.  *     fill-column: 78
  939.  * End:
  940.  */
  941.