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 / BootPOWERLILO.ycp < prev    next >
Text File  |  2006-11-29  |  33KB  |  1,096 lines

  1.  
  2. /**
  3.  * File:
  4.  *      modules/BootPOWERLILO.ycp
  5.  *
  6.  * Module:
  7.  *      Bootloader installation and configuration
  8.  *
  9.  * Summary:
  10.  *      Module containing specific functions for POWERLILO configuration
  11.  *      and installation
  12.  *
  13.  * Authors:
  14.  *      Jiri Srain <jsrain@suse.cz>
  15.  *      Joachim Plack <jplack@suse.de>
  16.  *      Olaf Dabrunz <od@suse.de>
  17.  *
  18.  * $Id: BootPOWERLILO.ycp 34587 2006-11-24 16:02:55Z odabrunz $
  19.  *
  20.  */
  21.  
  22. {
  23. module "BootPOWERLILO";
  24.  
  25. textdomain "bootloader";
  26.  
  27. import "Arch";
  28. import "BootArch";
  29. import "BootCommon";
  30. import "Kernel";
  31. import "Mode";
  32. import "Pkg";
  33. import "Stage";
  34. import "Storage";
  35.  
  36. /*
  37.  * This whole code is a big mess. To have a solution at all I included and
  38.  * adapted copies of the code from the old BootPPC.ycp, from common code in
  39.  * lilolike.ycp and others.
  40.  *
  41.  * od - February and March 2006
  42.  */
  43.  
  44. // change the OpenFirmware variable 'boot-device' on CHRP or new PowerMacs
  45. global boolean of_defaultdevice = true;
  46.  
  47. // partition number for the bootloader (either 41PReP boot or Apple_HFS)
  48. // start with disabled value and let the partition scanner find a match.
  49. global string prep_boot_partition = "";
  50.  
  51. // map available of 41 PReP partitions, used on iSeries and CHRP
  52. global list<string> prep_boot_partitions = [];
  53.  
  54. // PReP boot partitions that were proposed by partitioner to install BL
  55. global list<string> install_prep_boot_partitions = [];
  56.  
  57. // saved ID of the base installation source
  58. global integer base_source = -1;
  59.  
  60. // iSeries specific global settings
  61.  
  62. // filename for the iSeries kernel, for streamfile *STMF booting
  63. global string   iseries_streamfile  = "/boot/suse_linux_bootfile";
  64.  
  65. // write the install kernel to slot A, for rescue purpose
  66. global boolean  iseries_write_slot_a = false;
  67.  
  68. // write the kernel to slot B
  69. global boolean  iseries_write_slot_b = false;
  70.  
  71. // write the kernel to an 41 PReP boot partition
  72. global boolean  iseries_write_prepboot = false;
  73.  
  74. // write the kernel to file, this must be transfered to OS/400
  75. global boolean  iseries_write_streamfile = false;
  76.  
  77. // current board attribs
  78. global boolean prep_only_active = true;
  79. global boolean prep_only_iseries_vd = true;
  80. global boolean prep_only_primary = true;
  81. global boolean prep_same_disk_as_root = true;
  82. global list table_items = [];
  83. global string boot_device = "";
  84.  
  85. string board_type = nil;
  86.  
  87.  
  88. global define string getBoardType ();
  89. global define void setBoardType (string board);
  90. global define void currentBoardInit ();
  91.  
  92. include "bootloader/ppc/misc.ycp";
  93. include "bootloader/ppc/prep.ycp";
  94. include "bootloader/ppc/chrp.ycp";
  95. include "bootloader/ppc/iseries.ycp";
  96.  
  97. /*
  98.  * include ppc specific help messages
  99.  */
  100. include "bootloader/ppc/helps.ycp";
  101.  
  102. /*
  103.  * read my dialogs
  104.  */
  105. include "bootloader/routines/popups.ycp"; // define confirmSectionDeletePopup
  106. include "bootloader/generic/dialogs.ycp";
  107.  
  108.  
  109. // misc. functions
  110.  
  111. global define void initBoardType () {
  112.     if (Arch::board_iseries ())
  113.     {
  114.     board_type = "iseries";
  115.     }
  116.     else if (Arch::board_prep ())
  117.     {
  118.     board_type = "prep";
  119.     }
  120.     else if (Arch::board_chrp ())
  121.     {
  122.     board_type = "chrp";
  123.     }
  124.     else if (Arch::board_mac_new ())
  125.     {
  126.     board_type = "mac_new";
  127.     }
  128.     else if (Arch::board_mac_old ())
  129.     {
  130.     board_type = "mac_old";
  131.     }
  132.     else
  133.     {
  134.     board_type = "unknown";
  135.     }
  136.     y2milestone ("setting board type to: %1", board_type);
  137. }
  138.  
  139. global define string getBoardType () {
  140.     if (board_type == nil)
  141.         initBoardType ();
  142.     return board_type;
  143. }
  144.  
  145. global define void setBoardType (string board) {
  146.     board_type = board;
  147.     currentBoardInit ();
  148. }
  149.  
  150. /**
  151.   * Initialize the attribute of currently used board type
  152.   */
  153.  global define void currentBoardInit () {
  154.      if (getBoardType () == "iseries")
  155.      {
  156.        iSeriesInit ();
  157.      }
  158.      else if (getBoardType () == "prep")
  159.      {
  160.        PRePInit ();
  161.      }
  162.      else if (getBoardType () == "chrp")
  163.      {
  164.        CHRPInit ();
  165.      }
  166.      // TODO other boards
  167.  }
  168.  
  169.  
  170. /**
  171.  * Create section for bootable image
  172.  * @param   title   string    the section name to create (untranslated)
  173.  * @return        map        describes the section
  174.  */
  175. map<string,any> CreateImageSection (string title) {
  176.  
  177.     // FIXME: This really should be a function and not be duplicated in
  178.     //        BootCommon.ycp (although that code there also handles wildcard
  179.     //        entries for lilo)
  180.     // FIXME:
  181.     // This only works in the installed system (problem with GetFinalKernel))),
  182.     // in all other cases we use the symlinks.
  183.  
  184.     string image_fn = "";
  185.     string initrd_fn = "";
  186.  
  187.     if (Mode::normal ()) {
  188.     // Find out the file names of the "real" kernel and initrd files, with
  189.     // version etc. pp. whatever (currently version-flavor) attached.
  190.     //
  191.     // First, get the file names in the "selected" kernel package,
  192.     string kernel_package = Kernel::GetFinalKernel();
  193.     list<string> files = Pkg::PkgGetFilelist( kernel_package, `any );
  194.     y2milestone ("kernel package %1 has these files: %2", kernel_package, files);
  195.  
  196.     // then find the first file that matches the arch-dependent kernel file
  197.     // name prefix and the initrd filename prefix.
  198.     string kernel_prefix = "/boot/" + Kernel::GetBinary ();
  199.     string initrd_prefix = "/boot/initrd";
  200.  
  201.     list<string> files_filtered = filter (string file, files, {
  202.         return ( substring(file, 0, size(kernel_prefix)) == kernel_prefix );
  203.     });
  204.     image_fn = files_filtered[0]:"";
  205.  
  206.     files_filtered = filter (string file, files, {
  207.         return substring(file, 0, size(initrd_prefix)) == initrd_prefix ;
  208.     });
  209.     initrd_fn = files_filtered[0]:"";
  210.     } else {
  211.     // code removed: no wildcard entries possible on ppc (yaboot)
  212.     image_fn = "/boot/" + Kernel::GetBinary ();
  213.     initrd_fn = "/boot/initrd";
  214.     }
  215.     // done: image_fn and initrd_fn are the results
  216.     y2milestone ("image_fn: %1 initrd_fn: %2", image_fn, initrd_fn);
  217.  
  218.     map<string,any> ret = $[
  219.     "type" : "image",
  220.     "name" : title,
  221.     "original_name" : title,
  222.     "image" : image_fn,
  223.     "initrd" : initrd_fn,
  224.     "root" : BootCommon::RootPartitionDevice,
  225.     // "": do not include resume parameter on ppc
  226.     "append" : BootArch::DefaultKernelParams (""),
  227.     "__auto" : true,
  228.     "__changed" : false,
  229.     "__devs" : [BootCommon::BootPartitionDevice, BootCommon::RootPartitionDevice],
  230.     ];
  231.     return ret;
  232. }
  233.  
  234. /**
  235.   * Choose a boot partition on pmac
  236.   * type == Apple_HFS|Apple_Bootstrap && size < 20 cyl
  237.   * @return string device name of pmac boot partition
  238.   */
  239. string GoodPmacBootPartition() {
  240.     y2milestone ("Detecting pmac boot partition");
  241.     map<string,map> targetMap = (map<string,map>)Storage::GetTargetMap ();
  242.     y2milestone ("TargetMap: %1", targetMap);
  243.  
  244.     list<string> boot_partitions = [];
  245.     string selected_boot_partition = "";
  246.  
  247.     foreach (string dname, map ddata, targetMap, ``{
  248.     list<map> partitions = ddata["partitions"]:[];
  249.     y2milestone ("Partitions: %1", partitions);
  250.  
  251.     // does this device contain the root partition?
  252.     boolean hasrootdev = ( find (map p, partitions, ``(
  253.         (! p["delete"]:false)
  254.         && p["device"]:"" == BootCommon::RootPartitionDevice
  255.         && !contains( [`lvm, `evms, `sw_raid], p["type"]:`primary )
  256.     )) != nil );
  257.  
  258.     // find possible boot partitions
  259.     partitions = filter (map p, partitions, ``(
  260.         (! p["delete"]:false)
  261.         && is (p["fsid"]:nil, integer)
  262.         // both partition types Apple_Bootstrap and Apple_HFS can be
  263.         // handled by PPC lilo; yast2-storage maps both to fsid 258
  264.         && (p["fsid"]:nil == 258)
  265.         // the partition should be smaller than 20 cylinders (PPC lilo
  266.         // takes that size as well); estimating the kiBytes:
  267.         // 255 heads * 63 sectors * 20 cylinders * 512 bytes / 1024 bytes =
  268.         // 160650 kiBytes
  269.         && (p["size_k"]:0 < 160650)
  270.         && !contains( [`lvm, `evms, `sw_raid], p["type"]:`primary )
  271.     ));
  272.     y2milestone ("Filtered existing partitions: %1", partitions);
  273.  
  274.     // found a boot partition on the same device as the root partition?
  275.     if (hasrootdev && size (partitions) > 0
  276.         && selected_boot_partition == "")
  277.     {
  278.         y2milestone ("Selected pmac boot partition %1 on device with root partition %2",
  279.              partitions[0, "device"]:"", BootCommon::RootPartitionDevice);
  280.         selected_boot_partition = partitions[0, "device"]:"";
  281.     }
  282.  
  283.     // collect found boot partitions
  284.     boot_partitions = (list<string>)merge (boot_partitions,
  285.         (list<string>)maplist (map p, partitions, ``(
  286.         p["device"]:""
  287.         ))
  288.     );
  289.     });
  290.     y2milestone ("Detected pmac boot partitions: %1", boot_partitions);
  291.  
  292.     if (selected_boot_partition == "")
  293.     {
  294.         selected_boot_partition = boot_partitions[0]:"";
  295.     }
  296.     y2milestone ("Selected pmac boot partition: %1", selected_boot_partition);
  297.     return selected_boot_partition;
  298. }
  299.  
  300. /**
  301.   * Propose the location of the root device on disk and the boot device (if
  302.   * any), according to the subarchitecture.
  303.   * Results are stored in global variables.
  304.   *
  305.   */
  306. global void LocationProposal () {
  307.     BootCommon::DetectDisks ();
  308.     // del_parts is used by FixSections() in lilolike.ycp (imported by BootCommon.ycp)
  309.     BootCommon::del_parts = BootCommon::getPartitionList (`deleted);
  310.     boolean disks_changed = BootCommon::RefreshDisks();
  311.  
  312.     if (updatePrepBootPartitions () || prep_boot_partition == "")
  313.     {
  314.     // TODO warning to user
  315.     choosePrepBootPartition ();
  316.     }
  317.  
  318. /*  FIXME: remove this code (it was a simple proposal)
  319.     // get map of lists: mountpoint -> [partitionName, fsid, targetdevice, raid_type]
  320.     map mp = Storage::GetMountPoints();
  321.  
  322.     y2milestone( "mountPoints %1", mp );
  323.  
  324.     BootCommon::RootPartitionDevice = mp["/", 0]:"";
  325.     if (BootCommon::RootPartitionDevice == "")
  326.     y2error ("No mountpoint for / !!");
  327.     else
  328.     y2milestone("Root partition is %1", BootCommon::RootPartitionDevice);
  329. */
  330.  
  331.     string arch = BootCommon::exports["arch"]:"chrp";
  332.     if ( arch == "chrp" ) {
  333. /*  FIXME: remove this code (it was a simple proposal)
  334.     // FIXME: really detect the boot partition (instead of leaving this to
  335.     // lilo), see /lib/lilo/lilo-chrp.lib:76 (ie. GoodPrepOrFatPartition()
  336.     // functionality)
  337.     BootCommon::BootPartitionDevice =
  338.         regexpsub (BootCommon::RootPartitionDevice, "^(.*[^0-9])[0-9]*", "\\1");
  339.     if (BootCommon::BootPartitionDevice == nil)
  340.         BootCommon::BootPartitionDevice = BootCommon::RootPartitionDevice;
  341. */
  342.     BootCommon::BootPartitionDevice = prep_boot_partition;
  343.     // also set as default value in widget
  344.     BootCommon::change_widget_default_value("boot_chrp_custom", prep_boot_partition);
  345.     }
  346.     else if ( arch == "prep" ) {
  347.     BootCommon::BootPartitionDevice = prep_boot_partition;
  348.     BootCommon::change_widget_default_value("boot_prep_custom", prep_boot_partition);
  349.     }
  350.     else if ( arch == "iseries" ) {
  351.     BootCommon::BootPartitionDevice = prep_boot_partition;
  352.     BootCommon::change_widget_default_value("boot_iseries_custom", prep_boot_partition);
  353.     }
  354.     else if ( arch == "pmac" ) {
  355.     BootCommon::BootPartitionDevice = GoodPmacBootPartition();
  356.     BootCommon::change_widget_default_value("boot_pmac_custom", BootCommon::BootPartitionDevice);
  357.     }
  358.  
  359.     // These need to be set, for POWERLILO probably only to interface with
  360.     // autoyast, others base subsequent decisions on this.
  361.     // See ConfigureLocation() in lilolike.ycp.
  362.     //
  363.     // Mini-discussion: If autoyast is mainly used to clone configs, the
  364.     // loader_device and repl_mbr interface is enough, because loader_device
  365.     // simply contains the name of the device (partition, disk MBR, RAID
  366.     // device) to use for the bootloader.
  367.     // But if autoyast some day is used to transport configurations to less
  368.     // similar machines and setups, or to specify some sort of generic setup
  369.     // with special settings that will work on most machines, it may (or may
  370.     // not) be helpful to be able to specify boot_* variables in the autoyast
  371.     // file. This may apply better to the boot_* variables in BootGRUB.ycp
  372.     // though.
  373.     BootCommon::loader_device = BootCommon::BootPartitionDevice;
  374.     BootCommon::activate = true;
  375.     y2milestone("Boot partition is %1", BootCommon::loader_device);
  376. }
  377.  
  378. /**
  379.  * Propose sections to bootloader menu
  380.  * modifies internal sreuctures
  381.  */
  382. global void CreateSections () {
  383.     map<string,any> linux = CreateImageSection ("linux");
  384.  
  385.     // FIXME: I hate that i386 crap!!
  386.     if (haskey(linux, "kernel")) {
  387.         linux["image"] = linux["kernel"]:"/boot/vmlinux";
  388.         linux = remove(linux, "kernel");
  389.     };
  390.  
  391.     // FIXME: create an 'other' section for MACs to boot MacOS
  392.  
  393.     BootCommon::sections = [ linux, ];
  394. }
  395.  
  396. /**
  397.  * Propose global options of bootloader
  398.  * modifies internal structures
  399.  */
  400. global void CreateGlobals () {
  401.     // FIXME: for iseries there are typically more than one boot option;
  402.     //      boot = B
  403.     //      boot = /dev/iseries/vda1
  404.     //      boot = /boot/suse_linux_bootfile
  405.  
  406.     BootCommon::globals = $[
  407.     "activate": "true",
  408.     "default" : BootCommon::sections[0, "name"]:"",
  409.     "timeout" : "80",
  410.     ];
  411.  
  412.     string arch = BootCommon::exports["arch"]:"chrp";
  413.     map<string, string> boot_map = $[];
  414.  
  415.     y2milestone("RootPartDevice is %1",BootCommon::RootPartitionDevice);
  416.  
  417.     if ( arch == "chrp" ) {
  418.         boot_map = $[
  419.         "boot_chrp_custom" : BootCommon::BootPartitionDevice,
  420.         ];
  421.     }
  422.     else if ( arch == "prep" ) {
  423.         boot_map = $[
  424.         "boot_prep_custom" : BootCommon::BootPartitionDevice,
  425.     ];
  426.     }
  427.     else if ( arch == "pmac" ) {
  428.         boot_map = $[
  429.         "boot_pmac_custom" : BootCommon::BootPartitionDevice,
  430.         ];
  431.     }
  432.     else if ( arch == "iseries" ) {
  433.         boot_map = $[
  434.         "boot_slot"         : "B",
  435.         // FIXME: what file should be used here?
  436.             "boot_file"         : "/tmp/suse_linux_image",
  437.                    // GoodPRePPartitionOnVDisk(BootCommon::RootPartitionDevice)
  438.      ];
  439.  
  440.     // If we have an empty BootPartitionDevice on iseries, this means:
  441.     // do not boot from BootPartitionDevice but from some other place.
  442.     // Do not pass down to perl-Bootloader, lilo fails on an empty "boot =" line.
  443.     if (BootCommon::BootPartitionDevice != nil &&
  444.         BootCommon::BootPartitionDevice != "") {
  445.         boot_map["boot_iseries_custom"] = BootCommon::BootPartitionDevice;
  446.     }
  447.     }
  448.     // Finally merge results into "globals": new values replace old ones
  449.     BootCommon::globals = (map<string, string>) union(BootCommon::globals, boot_map);
  450.  
  451. }
  452.  
  453. /**
  454.  * Save the ID of the base installation source
  455.  * modifies internal variable
  456.  */
  457. global void SaveInstSourceId () {
  458.  
  459.     base_source = -1;
  460.  
  461.     // Find the source ID of the base product:
  462.     // list all products
  463.     list<map<string,any> > products =
  464.     Pkg::ResolvableProperties ("", `product, "");
  465.     y2internal ("products: %1", products);
  466.     // filter products to be installed
  467.     products = filter (map<string,any> p, products, {
  468.     return p["source"]:-1 != -1;
  469.     });
  470.     // get base products
  471.     list<map<string,any> > base_products =
  472.     filter (map<string,any> p, products, {
  473.         return p["category"]:"" == "base";
  474.     });
  475.     if (size (base_products) == 0)
  476.     base_products = products; // just to be safe in case of a bug...
  477.     list<integer> sources = maplist (map<string,any> p, base_products, {
  478.     return p["source"]:-1;
  479.     });
  480.     y2internal ("remaining products: %1, sources: %2",
  481.     products, sources);
  482.     sources = sort (sources);
  483.     base_source = sources[0]:-1;
  484.  
  485.     y2milestone ("Base source: %1", base_source);
  486. }
  487.  
  488. // general functions
  489.  
  490. /**
  491.   * Propose bootloader settings
  492.   */
  493. global define void Propose () {
  494.     y2debug ("Started propose: Glob: %1, Sec: %2",
  495.     BootCommon::globals, BootCommon::sections);
  496.  
  497.     // Need to remember inst source ID now to get the ISERIES64 file from the
  498.     // inst source later on (see Bug #165497, Comment #16). This won't work
  499.     // later during inst_finish, so we need to do it earlier -- only the
  500.     // proposal is a possible place.
  501.     SaveInstSourceId();
  502.  
  503.     // FIXME: make modern code out of these conditionals
  504.     //        - comments
  505.     //        - simplify
  506.     //        - check validity
  507.     boolean initial_propose = true;
  508.     if (BootCommon::was_proposed)
  509.     {
  510.     // FIXME: autoyast settings are simply Import()ed and was_proposed is
  511.     // set to true. The settings for the current board still need to be
  512.     // initialized though. We do this every time the bootloader proposal is
  513.     // called, because it also does not harm (results for the board
  514.     // detection are cached both in Arch.ycp and in our variable
  515.     // board_type.) To fix: make the "where does the information come
  516.     // from", when, more clear and obvious (in the code and/or in docs).
  517.     if (Mode::autoinst ())
  518.     {
  519.         currentBoardInit ();
  520.     }
  521.     initial_propose = false;
  522.     }
  523.     else
  524.     {
  525.     currentBoardInit ();
  526.     }
  527.     y2milestone ("board type is: %1", board_type);
  528.  
  529.     // Get root and boot partition (if any)
  530.     LocationProposal();
  531.  
  532.     if (BootCommon::sections == nil || size (BootCommon::sections) == 0)
  533.     {
  534.         CreateSections ();  // make an initial proposal for at least one section
  535.         BootCommon::kernelCmdLine = Kernel::GetCmdLine ();
  536.     }
  537.     else
  538.     {
  539.     if (Mode::autoinst ())
  540.     {
  541.         y2debug ("Nothing to do in AI mode if sections exist");
  542.     }
  543.     else
  544.         BootCommon::FixSections (BootPOWERLILO::CreateSections);
  545.     }
  546.  
  547.     if (BootCommon::globals == nil ||
  548.     // consider globals empty even if lines_cache_id is present
  549.     size (filter(string key, any v, BootCommon::globals, {
  550.         return key != "lines_cache_id";
  551.         })) == 0)
  552.     {
  553.         CreateGlobals ();
  554.     }
  555.     else
  556.     {
  557.     if (Mode::autoinst ())
  558.     {
  559.         y2debug ("Nothing to do in AI mode if globals are defined");
  560.     }
  561.     else
  562.         BootCommon::FixGlobals ();
  563.     }
  564.  
  565.     y2milestone ("Proposed sections: %1", BootCommon::sections);
  566.     y2milestone ("Proposed globals: %1", BootCommon::globals);
  567. }
  568.  
  569.  
  570.     /**
  571.       * Propose bootloader settings
  572.       *
  573.     global define void Propose () {
  574.     boolean initial_propose = true;
  575.     if (BootCommon::was_proposed)
  576.     {
  577.         initial_propose = false;
  578.     }
  579.     else
  580.     {
  581.         currentBoardInit ();
  582.     }
  583.         BootCommon::DetectDisks ();
  584.     BootCommon::del_parts = BootCommon::getPartitionList (`deleted);
  585.     boolean disks_changed = BootCommon::RefreshDisks();
  586.  
  587.     if (updatePrepBootPartitions () || prep_boot_partition == "")
  588.     {
  589.         // TODO warning to user
  590.         choosePrepBootPartition ();
  591.     }
  592.  
  593.         if ( getBoardType () == "iseries" )
  594.         {
  595.         iSeriesPropose (initial_propose);
  596.         }
  597.         else if ( getBoardType () == "prep" )
  598.         {
  599.         PRePPropose (initial_propose);
  600.         }
  601.         else if ( getBoardType () == "chrp" )
  602.         {
  603.         CHRPPropose (initial_propose);
  604.     }
  605.  
  606.     if (BootCommon::sections == nil || size (BootCommon::sections) == 0)
  607.     {
  608.         createSections ();
  609.         BootCommon::kernelCmdLine = Kernel::GetCmdLine ();
  610.     }
  611.     else
  612.     {
  613.             if (Mode::autoinst ())
  614.             {
  615.         y2debug ("nothing to to in AI mode if sections exist");
  616.                 // TODO whatever will be needed
  617.             }
  618.             else
  619.         fixSections (disks_changed);
  620.     }
  621.     if (BootCommon::globals == nil || size (BootCommon::globals) == 0)
  622.     {
  623.         createGlobals ();
  624.     }
  625.     else
  626.     {
  627.             if (Mode::autoinst ())
  628.             {
  629.         y2debug ("nothing to to in AI mode if globals are defined");
  630.                 // TODO whatever will be needed
  631.             }
  632.             else
  633.         fixGlobals (disks_changed);
  634.     }
  635.     }
  636.  
  637.     */
  638.  
  639. /**
  640.   * Export bootloader settings to a map
  641.   * @return bootloader settings
  642.   */
  643. global define map Export () {
  644.     map exp = $[
  645.         "global": BootCommon::globals,
  646.         "sections" : BootCommon::sections,
  647.         "activate" : BootCommon::activate,
  648.         ];
  649.     return exp;
  650. }
  651.  
  652.  
  653. /**
  654.   * Import settings from a map
  655.   * @param settings map of bootloader settings
  656.   * @return boolean true on success
  657.   */
  658. global define boolean Import (map settings) {
  659.     BootCommon::globals = settings["global"]:$[];
  660.     BootCommon::sections = settings["sections"]:[];
  661.     BootCommon::activate = settings["activate"]:false;
  662.     return true;
  663. }
  664.  
  665.  
  666. /**
  667.  * Read settings from disk
  668.  * @return boolean true on success
  669.  */
  670. global boolean Read (boolean reread) {
  671.     BootCommon::InitializeLibrary (reread, "ppc");
  672.     if (reread) {
  673.     BootCommon::ReadFiles ();
  674.     }
  675.     // Do we have to detect disks ?
  676.     // in /src/routines/lilolike.ycp is usesless for PPC (calls FindMBRDisk)
  677.     // BootCommon::DetectDisks ();
  678.  
  679.     boolean ret = BootCommon::Read (false);
  680.     y2milestone (":: Read globals: %1", BootCommon::globals);
  681.  
  682.     importMetaData();
  683.  
  684.     return ret;
  685. }
  686.  
  687.  
  688. /**
  689.  * Reset bootloader settings
  690.  */
  691. global define void Reset (boolean init) {
  692.     // Reset global variables to default values
  693.     prep_boot_partition = "";
  694.     prep_boot_partitions = [];
  695.     install_prep_boot_partitions = [];
  696.     BootCommon::Reset (init);
  697. }
  698.  
  699.  
  700. /**
  701.  * Save all bootloader configuration files to the cache of the PlugLib
  702.  * PlugLib must be initialized properly !!!
  703.  * @param clean boolean true if settings should be cleaned up (checking their
  704.  *  correctness, supposing all files are on the disk
  705.  * @param init boolean true to init the library
  706.  * @param flush boolean true to flush settings to the disk
  707.  * @return boolean true if success
  708.  */
  709. global boolean Save (boolean clean, boolean init, boolean flush) {
  710.     boolean ret = true;
  711.  
  712.     // FIXME: this is currently a copy from BootCommon::Save
  713.     if (clean)
  714.     {
  715.     BootCommon::RemoveUnexistentSections ("", "");
  716.     // FIXME: this is not needed, unclear code
  717.     // BootCommon::UpdateInitrdLine ();
  718.     BootCommon::UpdateAppend ();
  719.     }
  720.  
  721.     if (! BootCommon::InitializeLibrary (init, "ppc"))
  722.         // send current disk/partition information to perl-Bootloader
  723.     BootCommon::SetDiskInfo ();
  724.  
  725.     // Sanity check the sections list: we can only pass strings
  726.     // through the perl interface
  727.     list<map<string,string> > sects = maplist (map<string,any> s, BootCommon::sections, {
  728.     return (map<string,string>)
  729.         filter (string k, any v, s, { return is (v, string); });
  730.     });
  731.  
  732.     // convert root device names in sections to the device names indicated by
  733.     // "mountby"
  734.     sects = maplist (map<string,string> s, sects, {
  735.     s["root"] = BootCommon::Dev2MountByDev(s["root"]:"");
  736.     return s;
  737.     });
  738.  
  739.     // FIXME: remove all mountpoints of type 'boot/boot' through some Storage::<func>
  740.  
  741.     // FIXME: set one mountpoint 'boot/boot' for every boot target means all
  742.     // partitions in 'boot_<arch>_custom' and 'clone' (chrp)
  743.  
  744.     // ret = ret && BootCommon::SetDeviceMap (device_mapping);
  745.     ret = ret && BootCommon::SetSections (sects);
  746.     ret = ret && BootCommon::SetGlobal (BootCommon::globals);
  747.     if (flush)
  748.     ret = ret && BootCommon::CommitSettings ();
  749.  
  750.     return ret;
  751. }
  752.  
  753.  
  754. /**
  755.   * Display bootloader summary
  756.   * @return a list of summary lines
  757.   */
  758. global define list<string> Summary () {
  759.     list<string> result = [];
  760.  
  761.     // FIXME:
  762.     //    - evaluate and use the text from iSeriesSummary(), PRePSummary() and
  763.     //      CHRPSummary()
  764.     //  - add the cases for mac_old and mac_new (see BootPPC::Summary())
  765.  
  766.     // summary text, %1 is bootloader name
  767.     result = add(
  768.     result,
  769.     sformat(
  770.         _("Boot loader type: %1"),
  771.         BootCommon::getLoaderName (BootCommon::getLoaderType (false), `summary)
  772.     )
  773.     );
  774.  
  775.     // summary text for boot loader locations, sum up all locations to one string
  776.     string boot_loader_locations =
  777.         mergestring(
  778.         filter( string bll,
  779.         maplist( string key, any value, BootCommon::global_options, {
  780.             return (substring(key,0,5) == "boot_")
  781.                     ? BootCommon::globals[key]:"" : "";
  782.         }),
  783.             { return bll != ""; }
  784.         ),
  785.         ", "
  786.     );
  787.     result = add (result, sformat (_("Location: %1"), boot_loader_locations));
  788.  
  789.     list<string> sects = [];
  790.     foreach (map<string,any> s, BootCommon::sections, {
  791.         string title = s["name"]:"";
  792.     // section name "suffix" for default section
  793.         string def = (title == BootCommon::globals["default"]:"")
  794.       ? _(" (default)")
  795.       : "";
  796.         sects = add (sects, sformat ("%1%2", title, def));
  797.     });
  798.     // summary text. %1 is list of bootloader sections
  799.     result = add (result, sformat (_("Sections: %1"),
  800.         String::EscapeTags (mergestring (sects, ", "))));
  801.  
  802.     // FIXME: does the following code make any sense for ppc? (see also #163387)
  803.     // It seems not. (We do not do this, cf. jplack.) Keeping the code cadaver
  804.     // around until finally ready for removal.
  805.     // if (BootCommon::loader_device == "/dev/null")
  806.     //    // summary text
  807.     //    result = add (result,
  808. //        _("Do not install boot loader; just create configuration files"));
  809.     return result;
  810. }
  811.  
  812.  
  813. /**
  814.  * Update read settings to new version of configuration files
  815.  */
  816. global void Update () {
  817.  
  818.    /**
  819.     * Firstly update sections of bootloader configuration and modify internal
  820.     * structures as needed. This means right now:
  821.     *
  822.     * - no change of "resume=" parameter in append entry, not used on ppc yet
  823.     * - delete console= parameters as console autodetection now works
  824.     */
  825.  
  826.     // This function has been copied from lilolike.ycp::UpdateSections and
  827.     // adapted to conform with the image parameter
  828.     // BootPOWERLILO.ycp/perl-Bootloader uses. Some unneeded code has been
  829.     // removed.
  830.     // FIXME: SLES9 -> SLES10 update: check loader_type = lilo in
  831.     // /etc/sysconfig/bootloader
  832.  
  833.     // take current sections as starting point
  834.     list<map<string,any> > updated_sections = BootCommon::sections;
  835.     boolean linux_resume_added = false;
  836.  
  837.     map<string,any> default_sect = CreateImageSection("linux");
  838.     string default_name = default_sect["name"]:"";
  839.  
  840.     // assumption is that all of the following section names ar "good" names
  841.     // meaning that we will return a valid section description from
  842.     // CreateImageSection for them.
  843.     list<string> sections_to_recreate = ["linux"];
  844.  
  845.     updated_sections = maplist (map<string,any> s, updated_sections, {
  846.     string name = s["name"]:"";
  847.     string oname = s["original_name"]:name;
  848.  
  849.     // if we find a section that looks like it has been initially proposed
  850.     // from the installer, replace with the actual "good" proposal
  851.     if (contains(sections_to_recreate, oname)) {
  852.         sections_to_recreate = filter (string this_name,
  853.         sections_to_recreate, ``(this_name != oname)
  854.         );
  855.         // check for a new global default if oname != name
  856.         if ( name == BootCommon::globals["default"]:"" ) {
  857.             // we assume that the new name produced by CreateImageSection
  858.             // will be oname
  859.         BootCommon::globals["default"] = oname;
  860.         }
  861.         return CreateImageSection(oname);
  862.     }
  863.  
  864.     // else adjust the entries of the found section according to some
  865.     // fancy rules
  866.     foreach (string key, ["image", "initrd"], {
  867.         string value = s[key]:"";
  868.         // FIXME: check whether this is code for update from SLES8?
  869.         //        then we would delete it.
  870.         if (regexpmatch (value, "^.*\.shipped.*$"))
  871.         {
  872.         value = regexpsub (value,
  873.             "^(.*)\.shipped(.*)$", "\\1\\2");
  874.         }
  875.         else if (regexpmatch (value, "^.*\.suse.*$"))
  876.         {
  877.         value = regexpsub (value,
  878.             "^(.*)\.suse(.*)$", "\\1\\2");
  879.         }
  880.         s[key] = value;
  881.     });
  882.  
  883.  
  884.     // update root= entry in selected sections as the device naming
  885.     // changes in the linux kernel from time to time ...
  886.     if (contains (BootCommon::update_section_types, oname) && haskey(s, "root"))
  887.     {
  888.         y2milestone ("Updating root device of section %1", name);
  889.         s["root"] = BootCommon::UpdateDevice (s["root"]:"");
  890.     }
  891.  
  892.     // handle the append line
  893.     string append = s["append"]:"";
  894.  
  895.     // FIXME: how should we handle root= entries in append= lines?
  896.  
  897.     // add additional kernel parameters to the end of the append entry
  898.     // of special image section 'linux'
  899.     //
  900.     if (oname == "linux") {
  901.         foreach (string o, BootCommon::ListAdditionalKernelParams (), {
  902.             append = BootCommon::setKernelParamToLine (append, o, "false");
  903.         });
  904.         append = append + " " + BootCommon::GetAdditionalKernelParams ();
  905.  
  906.         if (BootCommon::getKernelParamFromLine (append, "splash") == "false")
  907.             append = BootCommon::setKernelParamToLine (append, "splash", "silent");
  908.     }
  909.  
  910.     // remove console= entries from kernel parameters, console auto
  911.     // detection now works. For special sections take what's given on boot
  912.     // command line
  913.     string console = "false"; // false means delete to 'setKernelParamToLine'
  914.     if (contains (BootCommon::update_section_types, oname))
  915.     {
  916.         console = BootCommon::getKernelParamFromLine (Kernel::GetCmdLine(), "console") ;
  917.     }
  918.     append = BootCommon::setKernelParamToLine (append, "console", console);
  919.  
  920.     // finally append entry is written back
  921.     if (append != "")
  922.         s["append"] = append;
  923.     else
  924.         s = remove(s, "append");
  925.  
  926.     return s;
  927.     });
  928.  
  929.     // if there was no original section matching the sections we want to
  930.     // recreate, so do prepend or append newly created sections to the list of
  931.     // updated sections
  932.     foreach (string section_name, sections_to_recreate, {
  933.         map<string,any> new_section =  CreateImageSection(section_name);
  934.     if (section_name == "linux")
  935.         updated_sections = prepend (updated_sections, new_section);
  936.     else
  937.         updated_sections = add (updated_sections, new_section);
  938.     });
  939.  
  940.     BootCommon::sections = updated_sections;
  941.     y2milestone("finished updating sections: %1", updated_sections);
  942.     // End of UpdateSections ();
  943.  
  944.    /**
  945.     * Secondly update global settings of bootloader configuration:
  946.     *
  947.     * - no change of 'activate'
  948.     * - no change of 'timeout'
  949.     * - no change of default section
  950.     * - no change of default initrd
  951.     * - update device names that might have changed in as needed
  952.     * - delete console= parameters as console autodetection now works
  953.     */
  954.     BootCommon::loader_device
  955.     = BootCommon::UpdateDevice (BootCommon::loader_device);
  956.  
  957.     // update device naming of default root and boot_* entries
  958.     foreach (string key, ["root", "boot_prep_custom", "boot_chrp_custom",
  959.               "boot_iseries_custom","boot_pmac_custom", "clone"], {
  960.     if (haskey(BootCommon::globals, key)) {
  961.         y2milestone ("Updating global %1= setting, currently %2",
  962.              key, BootCommon::globals[key]:"");
  963.         BootCommon::globals[key] =
  964.           BootCommon::UpdateDevice (BootCommon::globals[key]:"");
  965.     }
  966.     });
  967.  
  968.     // remove console= entries from globals, console auto detection now works
  969.     if (haskey (BootCommon::globals, "append")) {
  970.         string append = BootCommon::globals["append"]:"";
  971.     append = BootCommon::setKernelParamToLine (append, "console", "false");
  972.     if (append != "")
  973.         BootCommon::globals["append"] = append;
  974.     else
  975.         BootCommon::globals = remove(BootCommon::globals, "append");
  976.     }
  977. }
  978.  
  979. /**
  980.   * Write bootloader settings to disk
  981.   * @return boolean true on success
  982.   */
  983. global define boolean Write () {
  984.  
  985.     if (getBoardType () == "iseries")
  986.     {
  987.     iSeriesWrite ();
  988.     }
  989.  
  990.     boolean ret = BootCommon::UpdateBootloader ();
  991.  
  992.     ret = ret && BootCommon::InitializeBootloader ();
  993.     return ret;
  994. }
  995.  
  996.  
  997. global symbol WizardSequenzer() {
  998. /*
  999. blMainSequence () {
  1000.     map functions = getFunctions (BootCommon::getLoaderType (false));
  1001.     symbol () toEval = (symbol ())functions["wizard_sequencer"]:nil;
  1002.     if (toEval != nil)
  1003.     return toEval ();
  1004.     else
  1005.     return `generic;
  1006. */
  1007.     y2milestone("Call generic WizardSequenzer");
  1008.     return `generic_new;
  1009. }
  1010.  
  1011.  
  1012. global map<string,symbol()> Dialogs () {
  1013.     // PPC definitly needs other text modules
  1014.     return $[
  1015.     "loader"    : genericBootLoaderOptionsDialog,
  1016. //    "installation"    : ppcInstallDetailsDialog,
  1017.     ];
  1018. }
  1019.  
  1020.  
  1021. /**
  1022.  * Return map of provided functions
  1023.  * @return map map of functions (eg. $["write":BootPOWERLILO::Write])
  1024.  */
  1025. global map<string, any> GetFunctions () {
  1026.     return $[
  1027.     "export"       : Export,
  1028.     "import"       : Import,
  1029.     "read"           : Read,
  1030.     "reset"           : Reset,
  1031.     "propose"       : Propose,
  1032.     "save"           : Save,
  1033.     "summary"       : Summary,
  1034.     "update"       : Update,
  1035.     "write"           : Write,
  1036.     "widgets"       : genericWidgets,
  1037.     "wizard_sequencer" : WizardSequenzer,
  1038.     "dialogs"       : Dialogs,
  1039.     "section_types"       : section_types,
  1040.     ];
  1041. }
  1042.  
  1043. /**
  1044.   * Initializer of PowerLILO bootloader
  1045.   */
  1046. global void Initializer () {
  1047.     y2milestone ("Called PowerLILO initializer");
  1048.     BootCommon::current_bootloader_attribs = $[
  1049.     "propose" : true,
  1050.     "read" : true,
  1051.     "scratch" : true,
  1052.     "bootloader_on_disk" : true,
  1053.     ];
  1054.     BootCommon::help_messages = (map<string,string>)
  1055.         union(BootCommon::help_messages,
  1056.           mapmap(string key, string val, ppc_help_messages,
  1057.              { return $[ "ppc_" + key : val ]; }
  1058.              )
  1059.           );
  1060.     y2debug("Initialized help_messages to %1", BootCommon::help_messages);
  1061.     BootCommon::descriptions = (map<string,string>)
  1062.         union(BootCommon::descriptions,
  1063.           mapmap(string key, string val, ppc_descriptions,
  1064.              { return $[ "ppc_" + key : val ]; }
  1065.              )
  1066.           );
  1067.     y2debug("Initialized help_messages to %1", BootCommon::help_messages);
  1068.  
  1069.     BootCommon::InitializeLibrary (false, "ppc");
  1070.     importMetaData();
  1071. }
  1072.  
  1073. /**
  1074.   * Constructor
  1075.   */
  1076. global void BootPOWERLILO () {
  1077.     BootCommon::bootloader_attribs["ppc"] = $[
  1078.     "required_packages"    : ["lilo"],
  1079.     "loader_name"        : "ppc",
  1080.     "initializer"        : BootPOWERLILO::Initializer,
  1081.     ];
  1082. }
  1083.  
  1084. }
  1085.  
  1086. /*
  1087.  * Local variables:
  1088.  *     mode: ycp
  1089.  *     mode: font-lock
  1090.  *     mode: auto-fill
  1091.  *     indent-level: 4
  1092.  *     fill-column: 78
  1093.  * End:
  1094.  */
  1095.  
  1096.