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 / BootELILO.ycp < prev    next >
Text File  |  2006-11-29  |  13KB  |  480 lines

  1. /**
  2.  * File:
  3.  *      modules/BootELILO.ycp
  4.  *
  5.  * Module:
  6.  *      Bootloader installation and configuration
  7.  *
  8.  * Summary:
  9.  *      Module containing specific functions for ELILO configuration
  10.  *      and installation
  11.  *
  12.  * Authors:
  13.  *      Jiri Srain <jsrain@suse.cz>
  14.  *      Andreas Schwab <schwab@suse.de>
  15.  *
  16.  * $Id: BootELILO.ycp 30058 2006-04-12 12:01:03Z odabrunz $
  17.  *
  18.  */
  19.  
  20. {
  21.  
  22. // FIXME paths will be probably changed because of bugzilla 21644
  23.  
  24. module "BootELILO";
  25.  
  26. textdomain "bootloader";
  27.  
  28. import "BootArch";
  29. import "BootCommon";
  30. import "Kernel";
  31. import "Mode";
  32. import "Stage";
  33. import "Storage";
  34.  
  35. // private variables
  36.  
  37. /**
  38.   * Name of EFI entry when read settings
  39.   */
  40. global string old_efi_entry = nil;
  41.  
  42. /**
  43.   * Should be original EFI entry removed?
  44.   */
  45. global boolean remove_old_efi = true;
  46.  
  47. /**
  48.   * elilo.conf path
  49.   */
  50. global string elilo_conf_filename = "/boot/efi/SuSE/elilo.conf";
  51.  
  52. /**
  53.   * True if EFI entry should be recreated
  54.   */
  55. global boolean create_efi_entry = true;
  56.  
  57. /**
  58.   * True if the EFI layout was changed
  59.   */
  60. global boolean efi_layout_changed = false;
  61.  
  62. /**
  63.  * The name of the entry in the EFI menu
  64.  */
  65. global string efi_entry_name = "";
  66.  
  67. include "bootloader/elilo/misc.ycp";
  68. include "bootloader/elilo/widgets.ycp";
  69.  
  70.  
  71. // misc. functions
  72.  
  73.  
  74. /**
  75.  * Propose sections to bootloader menu
  76.  * modifies internal sreuctures
  77.  */
  78. global void CreateSections () {
  79.     map<string,any> linux = BootCommon::CreateLinuxSection ("linux");
  80.     map<string,any> failsafe = BootCommon::CreateLinuxSection ("failsafe");
  81.  
  82.     // append for default section is in global
  83.     // FIXME do it later
  84.     //    if (haskey (linux, "append"))
  85.     //      linux = remove (linux, "append");
  86.  
  87.     BootCommon::sections = [ linux, failsafe ];
  88. }
  89.  
  90.  
  91. /**
  92.  * Propose global options of bootloader
  93.  * modifies internal structures
  94.  */
  95. global void CreateGlobals () {
  96.     BootCommon::globals = $[
  97.     // FIXME do it later
  98.     //    "append" : BootArch::DefaultKernelParams (""),
  99.     "default" : BootCommon::translateSectionTitle ("linux"),
  100.     "timeout" : "8",
  101.     "prompt" : "1",
  102.     ];
  103.     // FIXME TODO in the library
  104.     /*    BootCommon::globals = [
  105.         $[ "key" : "prompt", "value" : true ],
  106.         $[ "key" : "read-only", "value" : true ],
  107.         $[ "key" : "relocatable", "value" : true ],
  108.     ];*/
  109. }
  110.  
  111.  
  112. // general functions
  113.  
  114.  
  115. /**
  116.   * Export bootloader settings to a map
  117.   * @return bootloader settings
  118.   */
  119. global define map Export () {
  120.     map ret = BootCommon::Export ();
  121.     ret["old_efi_entry"] = old_efi_entry;
  122.     ret["remove_old_efi"] = remove_old_efi;
  123.     ret["elilo_conf_filename"] = elilo_conf_filename;
  124.     ret["create_efi_entry"] = create_efi_entry;
  125.     return ret;
  126. }
  127.  
  128.  
  129. /**
  130.   * Import settings from a map
  131.   * @param settings map of bootloader settings
  132.   */
  133. global define boolean Import (map<string, any> settings) ``{
  134.     BootCommon::Import (settings);
  135.     old_efi_entry = (string) (settings["old_efi_entry"]:nil);
  136.     remove_old_efi = settings["remove_old_efi"]:true;
  137.     elilo_conf_filename = getEliloConfFilename ();
  138.     create_efi_entry
  139.         = settings["create_efi_entry"]:(settings["location"]:"" != "");
  140.     return true;
  141. }
  142.  
  143.  
  144. /**
  145.   * Propose bootloader settings
  146.   */
  147. global define void Propose () ``{
  148.     import "Product";
  149.     if (! BootCommon::was_proposed)
  150.     {
  151.         create_efi_entry = true;
  152.         efi_entry_name = Product::name;
  153.     }
  154.     if (! Stage::initial ())
  155.         create_efi_entry = true;
  156.     if (Mode::update ())
  157.         create_efi_entry = false;
  158.     elilo_conf_filename = getEliloConfFilename ();
  159.     BootCommon::DetectDisks ();
  160.     BootCommon::del_parts = BootCommon::getPartitionList (`deleted);
  161.  
  162.     if (BootCommon::sections == nil || size (BootCommon::sections) == 0)
  163.     {
  164.         CreateSections ();
  165.         BootCommon::kernelCmdLine = Kernel::GetCmdLine ();
  166.     }
  167.     else
  168.     {
  169.         if (Mode::autoinst ())
  170.         {
  171.         y2debug ("Nothing to do for propose in AI mode");
  172.         }
  173.         else
  174.         BootCommon::FixSections (BootELILO::CreateSections);
  175.     }
  176.     if (BootCommon::globals == nil || size (BootCommon::globals) == 0)
  177.     {
  178.         CreateGlobals ();
  179.     }
  180.  
  181.     if (efi_entry_name == "" || efi_entry_name == nil)
  182.     {
  183.         efi_entry_name = Product::name;
  184.     }
  185.     y2milestone ("EFI entry name: %1", efi_entry_name);
  186.     y2milestone ("Proposed sections: %1", BootCommon::sections);
  187.     y2milestone ("Proposed globals: %1", BootCommon::globals);
  188. }
  189.  
  190.  
  191. /**
  192.   * Read settings from disk
  193.   * @return boolean true on success
  194.   */
  195. global define boolean Read (boolean reread) ``{
  196.     import "Product";
  197.     boolean efi_entry_found = false;
  198.     elilo_conf_filename = getEliloConfFilename ();
  199.     // copy old elilo.conf from /boot/<something> to /etc in case of upgrade
  200.     // (if /etc/elilo.conf doesn't exist)
  201.     if (SCR::Read (.target.size, "/etc/elilo.conf") <= 0
  202.         && SCR::Read (.target.size, elilo_conf_filename) > 0)
  203.     {
  204.         SCR::Execute (.target.bash, sformat (
  205.         "/bin/cp %1 /etc/elilo.conf", elilo_conf_filename));
  206.     }
  207.     SCR::Execute (.target.bash, "/bin/touch /etc/elilo.conf");
  208.     BootCommon::DetectDisks ();
  209.     boolean ret = BootCommon::Read (reread);
  210.     efi_entry_name
  211.         = (string)SCR::Read (.sysconfig.bootloader.LOADER_LOCATION);
  212.     y2milestone ("EFI entry: %1", efi_entry_name);
  213.     // check for meaningless EFI entry name in sysconfig
  214.     if ("mbr" == efi_entry_name || "" == efi_entry_name
  215.         || nil == efi_entry_name)
  216.     {
  217.         string efi_path = BootCommon::replaceAll (
  218.         getEliloConfSubpath (), "/", "\\");
  219.         // Read Firmware setting from NVRam
  220.         map efi_status = (map)SCR::Execute (.target.bash_output, sformat (
  221.         "/usr/sbin/efibootmgr |grep \"%1\"", efi_path));
  222.         if (efi_status["exit"]:0 != 0)
  223.         {
  224.         efi_entry_name = Product::name;
  225.         }
  226.         else
  227.         {
  228.         string output = efi_status["stdout"]:"";
  229.         list lines = splitstring (output, "\n");
  230.         output = lines[0]:"";
  231.         if (regexpmatch (output, "Boot.*\* (.*)  HD"))
  232.         {
  233.             efi_entry_name
  234.             = regexpsub (output, "Boot.*\* (.*)  HD", "\\1");
  235.             efi_entry_found = true;
  236.         }
  237.         else
  238.         {
  239.             efi_entry_name = Product::name;
  240.         }
  241.         }
  242.     }
  243.     else
  244.     {
  245.         efi_entry_found = 0 == SCR::Execute (.target.bash, sformat (
  246.             "/usr/sbin/efibootmgr |grep \"%1\"", efi_entry_name));
  247.     }
  248.     create_efi_entry = false;
  249.     old_efi_entry = efi_entry_found ? efi_entry_name : (string)nil;
  250.     return ret;
  251. }
  252.  
  253.  
  254. /**
  255.   * Reset bootloader settings
  256.   */
  257. global define void Reset (boolean init) {
  258.     if (Mode::autoinst ())
  259.         return;
  260.     remove_old_efi = true;
  261.     create_efi_entry = true;
  262.     BootCommon::Reset(init);
  263. }
  264.  
  265. /**
  266.  * Save all bootloader configuration files
  267.  * @return boolean true if success
  268.  */
  269. global boolean Save (boolean clean, boolean init, boolean flush) {
  270.     BootCommon::globals["efi_entry_name"] = efi_entry_name;
  271.     // FIXME modify EFI? Entries to remove...
  272.     boolean ret = BootCommon::Save (clean, init, flush);
  273.     return ret;
  274. }
  275.  
  276. /**
  277.   * Display bootloader summary
  278.   * @return a list of summary lines
  279.   */
  280. global define list<string> Summary () {
  281.     // summary text, %1 is bootloader name (eg. LILO)
  282.     list<string> result = [ sformat (_("Boot loader type: %1"),
  283.         BootCommon::getLoaderName (BootCommon::getLoaderType (false), `summary)) ];
  284.     if ( efi_entry_name == "" || efi_entry_name == nil || !create_efi_entry )
  285.     {
  286.         result =
  287.             // summary text
  288.             add (result, _("Do Not Create EFI Boot Manager Entry"));
  289.     }
  290.     else
  291.     {
  292.         result = add (result, sformat (
  293.         // summary text, %1 is label of the entry of EFI boot manager
  294.         _("Create EFI Boot Manager Entry %1"),
  295.         efi_entry_name));
  296.     }
  297.     list<string> sects = [];
  298.     foreach (map<string,any> s, BootCommon::sections, {
  299.         string title = s["name"]:"";
  300.             // section name "suffix" for default section
  301.         string def = title == BootCommon::globals["default"]:"" ?
  302.           _(" (default)") :
  303.           "";
  304.         sects = add (sects, sformat ("%1%2", title, def));
  305.     });
  306.     // summary text. %1 is list of bootloader sections
  307.     result = add (result, sformat (_("Sections: %1"),
  308.         mergestring (sects, ", ")));
  309.     return result;
  310. }
  311.  
  312. /**
  313.  * Update read settings to new version of configuration files
  314.  */
  315. global define void Update () {
  316.     /*
  317.      * Update global options of bootloader
  318.      * modifies internal sreuctures
  319.      */
  320.     BootCommon::globals["timeout"] = "8";
  321.     BootCommon::globals["append"] = BootArch::DefaultKernelParams ("");
  322.  
  323.     BootCommon::UpdateSections (true, BootCommon::CreateLinuxSection);
  324.     // FIXME EFI entry name
  325. }
  326.  
  327.  
  328. /**
  329.   * Install the bootloader, display a popup with log if something
  330.   *  goes wrong
  331.   * @param command string command to install the bootloader
  332.   * @param logfile string filename of file used to write bootloader log
  333.   * @return boolean true on success
  334.   */
  335. // FIXME get rid of this function
  336. define boolean installBootLoader (string command, string logfile) {
  337.     y2milestone ("Running command %1", command);
  338.     map exit = (map)SCR::Execute (.target.bash_output, command);
  339.     boolean ret = 0 == exit["exit"]:1;
  340.     if (! ret)
  341.     {
  342.         y2milestone ("Exit code of %1: %2", command, exit["exit"]:-1);
  343.         string log = (string)SCR::Read (.target.string, logfile);
  344.         log = log + exit["stdout"]:"" + exit["stderr"]:"";
  345.         if (exit["exit"]:1 == 139)
  346.         {
  347.             // means: process received signal SIGSEGV
  348.             // please, use some usual translation
  349.             // proofreaders: don't change this text
  350.             log = log + _("Segmentation fault");
  351.         }
  352.  
  353.         errorWithLogPopup (sformat (
  354.             // error popup - label, %1 is bootloader name
  355.             _("Error Occurred while Installing %1"),
  356.             BootCommon::getLoaderName (BootCommon::getLoaderType (false), `summary)), log);
  357.     }
  358.     return ret;
  359. }
  360.  
  361.  
  362. /**
  363.   * Write bootloader settings to disk
  364.   * @return boolean true on success
  365.   */
  366. global define boolean Write () {
  367.     //    SCR::Execute (.target.bash, "/sbin/elilo");
  368.     boolean ret = BootCommon::UpdateBootloader ();
  369.   
  370.     if (BootCommon::location_changed || create_efi_entry)
  371.     {
  372.         // FIXME shuold be handled completly through the library
  373.         // remove existing end old menu entry
  374.         list<string> efi_entries_to_remove = toset ([
  375.         efi_entry_name,
  376.         remove_old_efi ? old_efi_entry : ""
  377.         ]);
  378.         efi_entries_to_remove = filter (
  379.         string e,
  380.         efi_entries_to_remove,
  381.         ``(    e != nil && e != "")
  382.     );
  383.  
  384.         foreach (string efi_label, efi_entries_to_remove, {
  385.         // delete bootentry for efi_label if available
  386.         string command = sformat(
  387.         "BOOTENTRY=\"" +
  388.         "`/usr/sbin/efibootmgr |grep \"%1\" |cut -f1 -d\* |cut -c5-`\";" +
  389.         "if [ \"$BOOTENTRY\" ]; then " + 
  390.             "/usr/sbin/efibootmgr --delete-bootnum --bootnum $BOOTENTRY -q;" + 
  391.         "fi",
  392.         efi_label
  393.         );
  394.         y2milestone ("Running command %1", command);
  395.         ret = 0 == SCR::Execute (.target.bash, command);
  396.     });
  397.  
  398.     map mp = Storage::GetMountPoints();
  399.     string boot_dev = mp[getEfiMountPoint (), 0]:"/boot/efi";
  400.     map splited = Storage::GetDiskPartition (boot_dev);
  401.     any boot_part = splited["nr"]:0;
  402.     any boot_disk = splited["disk"]:"";
  403.     y2milestone ("Disk: %1, Part: %2", boot_disk, boot_part);
  404.  
  405.     if (efi_entry_name != "" && efi_entry_name != nil)
  406.     {
  407.         string bl_logfile = "/var/log/YaST2/y2log_bootloader";
  408.         string bl_command = sformat (
  409.         "/usr/sbin/efibootmgr -v --create --label \"%1\" " +
  410.         "--disk %2 --part %3 " +
  411.         "--loader '\\efi\\SuSE\\elilo.efi' --write-signature >> %4 2>&1",
  412.         efi_entry_name, boot_disk, boot_part, bl_logfile);
  413.         ret = ret && installBootLoader (bl_command, bl_logfile);
  414.     }
  415.     }
  416.     return ret;
  417. }
  418.  
  419.  
  420. global map<string,symbol()> Dialogs () {
  421.     return $[];
  422. }
  423.  
  424. /**
  425.   * Return map of provided functions
  426.   * @return map map of functions (eg. $["write":``(BootLILO::Write ())])
  427.   */
  428. global define map GetFunctions () {
  429.     return $[
  430.     "dialogs" : Dialogs,
  431.     "export"  : Export,
  432.     "import"  : Import,
  433.     "read"      : Read,
  434.     "reset"      : Reset,
  435.     "propose" : Propose,
  436.     "save"      : Save,
  437.     "summary" : Summary,
  438.     "update"  : Update,
  439.     "write"      : Write,
  440.     "widgets" : Widgets,
  441.     ];
  442. }
  443.  
  444. /**
  445.  * Initializer of ELILO bootloader
  446.  */
  447. global void Initializer () {
  448.     y2milestone ("Called ELILO initializer");
  449.     BootCommon::current_bootloader_attribs = $[
  450.         "propose" : true,
  451.         "read" : true,
  452.         "scratch" : true,
  453.         "restore_mbr" : true,
  454.         "bootloader_on_disk" : true,
  455.     ];
  456. }
  457.  
  458. /**
  459.  * Constructor
  460.  */
  461. global define void BootELILO () {
  462.     BootCommon::bootloader_attribs["elilo"] = $[
  463.     "required_packages" : ["elilo"],
  464.     "loader_name" : "ELILO",
  465.     "initializer" : BootELILO::Initializer,
  466.     ];
  467. }
  468.  
  469. }
  470.  
  471. /*
  472.  * Local variables:
  473.  *     mode: ycp
  474.  *     mode: font-lock
  475.  *     mode: auto-fill
  476.  *     indent-level: 4
  477.  *     fill-column: 78
  478.  * End:
  479.  */
  480.