ACC SHELL
/**
* File:
* modules/BootCommon.ycp
*
* Module:
* Bootloader installation and configuration
*
* Summary:
* Data to be shared between common and bootloader-specific parts of
* bootloader configurator/installator, generic versions of bootloader
* specific functions
*
* Authors:
* Jiri Srain <jsrain@suse.cz>
* Joachim Plack <jplack@suse.de>
* Olaf Dabrunz <od@suse.de>
*
* $Id: BootCommon.ycp 62089 2010-06-02 15:08:27Z juhliarik $
*
*/
{
module "BootCommon";
textdomain "bootloader";
import "Arch";
import "GfxMenu";
import "HTML";
import "Mode";
import "PackageSystem";
import "Storage";
import "String";
import "Pkg";
import "Popup";
import "Package";
import "PackagesProposal";
import "BootStorage";
import "Linuxrc";
// General bootloader settings
/**
* map of global options and types for new perl-Bootloader interface
*/
global map<string,any> global_options = $[];
/**
* map of section options and types for new perl-Bootloader interface
*/
global map<string,any> section_options = $[];
/**
* boolean value indicate if "/" is on logical
* and primary /boot doesn't exist
*/
global boolean boot_device_on_logical = false;
/**
* map of global options and values
*/
global map<string,string> globals = $[];
/**
* list of section
*/
global list<map<string,any> > sections = [];
/**
* Saved change time from target map - proposal
*/
global integer cached_settings_base_data_change_time = nil;
/**
* device to save loader stage 1 to
* NOTE: this variable is being phased out. The boot_* keys in the globals map
* are now used to remember the selected boot location. Thus, we now have a
* list of selected loader devices. It can be generated from the information in
* the boot_* keys and the global variables (Boot|Root|Extended)PartitionDevice
* and mbrDisk by calling GetBootloaderDevices().
*/
//FIXME: need remove to read only loader location from perl-Bootloader
global string loader_device = nil;
// proposal helping variables
/**
* The kind of bootloader location that the user selected last time he went to
* the dialog. Used as a hint next time a proposal is requested, so the
* proposal can try to satisfy the user's previous preference.
* NOTE: this variable is being phased out. The boot_* keys in the globals map
* will be used to remember the last selected location.
* Currently, valid values are: mbr, boot, root, floppy, mbr_md, none
*/
//FIXME: need remove to read only loader location from perl-Bootloader
global string selected_location = nil;
/* These global variables and functions are needed in included files */
/**
* Parameters of currently used bootloader
*/
global map<string, any> current_bootloader_attribs = $[];
/**
* Parameters of all bootloaders
*/
global map<string,map<string, any> > bootloader_attribs = $[];
/**
* Name of currently edited section
*/
global string current_section_name = nil;
/**
* Index of current section, -1 for new created section
*/
global integer current_section_index = -1;
/**
* Curtrently edited section -- tmp store
*/
global map<string,any> current_section = $[];
/**
* Option types for different bootloaders
*/
global map<string,map<string,string> > opt_types = $[];
/**
* device holding MBR for bootloader
*/
global string mbrDisk = "";
/**
* was currently edited section changed (== true)
*/
global boolean one_section_changed = false;
/**
* Backup original MBR before installing bootloader
*/
global boolean backup_mbr = false;
/**
* Activate bootloader partition during installation?
*/
global boolean activate = false;
/** FATE #303548 - Grub: limit device.map to devices detected by BIOS
* Ask user if he wants to edit again bootloader settings
* It is used if device.map is limited and "boot" disk is out of range
* The range is the first 8 devices
*/
global boolean ask_user = false;
/**
* Replace MBR with generic code after bootloader installation?
*/
global boolean repl_mbr = false;
/**
* Kernel parameters at previous detection
*/
global string kernelCmdLine = "";
/**
* were settings changed (== true)
*/
global boolean changed = false;
global map<string,any> installed_version = $[];
global map<string,any> update_version = $[];
global map<string,string> edited_files = $[];
// common variables
/**
* type of bootloader to configure/being configured
* shall be one of "lilo", "grub", "elilo", "ppc", "zipl"
*/
string loader_type = nil;
// sysconfig variables
// installation proposal help variables
/**
* List of partitions deleted in primary proposal
*/
global list<string> del_parts = [];
// variables for storing data
// saving mode setting functions
/**
* map of save mode settings
*/
global map write_settings = $[];
// summary dialog state
/**
* Show verbose summary output
*/
global boolean verbose = false;
// ui help variables
string additional_failsafe_params = "";
// other variables
/**
* Settings of other bootloaders used when switching bootloader
*/
global map other_bl = $[];
// bootloader installation variables
/**
* Was the activate flag changed by user?
*/
global boolean activate_changed = false;
/**
* Save everything, not only changed settings
*/
global boolean save_all = false;
// state variables
/**
* was the propose function called (== true)
*/
global boolean was_proposed = false;
/**
* Were module settings read (== true)
*/
global boolean was_read = false;
/**
* Was bootloader location changed? (== true)
*/
global boolean location_changed = false;
/**
* Were configuration files manually edited and chamged?
*/
global boolean files_edited = false;
/**
* Has been files edited warning already shown?
*/
global boolean files_edited_warned = false;
/**
* time of last change of partitioning
*/
global integer partitioning_last_change = 0;
/**
* true if memtest was removed by user (manually) during the installation
* proposal
*/
//FIXME correct comment
global list<string> removed_sections = [];
/**
* The name of the default section as it was read
*/
global string read_default_section_name = "";
/**
* Types of sections that should be updated (changed device names)
*/
// FIXME: see FIXME in lilolike.ycp:899
global list<string> update_section_types = [ "floppy", "other" ];
// = [ "linux", "failsafe", "initrd", "floppy" ];
/**
* List of all supported bootloaders
*/
global list<string> bootloaders = ["lilo", "grub", "elilo",
"zipl", "ppc"];
/** FATE#305008: Failover boot configurations for md arrays with redundancy
* if true enable redundancy for md array
*/
global boolean enable_md_array_redundancy = nil;
/** FATE#305557: Enable SELinux for 11.2
* if true create /selinux directory
*/
global boolean enable_selinux = false;
global define string getLoaderType (boolean recheck);
global define list<string> getBootloaders ();
global define list<string> Summary ();
global map<string,any> CreateLinuxSection (string title);
global string UpdateSerialConsole (string append, string console);
global string examineMBR (string device);
global boolean ThinkPadMBR (string disk);
global boolean VerifyMDArray ();
/*
* help message and dscription definitions
*/
include "bootloader/routines/popups.ycp";
include "bootloader/routines/misc.ycp";
// FIXME: there are other archs than i386, this is not 'commmon'
include "bootloader/routines/lilolike.ycp";
include "bootloader/routines/lib_iface.ycp";
// interface to bootloader library
// FIXME 2x functions should not be finally here...
/**
* Check whether XEN is selected for installation resp. selected
* @return boolean true of XEN installed/selected
*/
global boolean XenPresent () {
boolean ret = (! contains (removed_sections, "xen"))
&& (Mode::test ()
|| (Mode::normal () && Pkg::IsProvided ("xen")
&& Pkg::IsProvided ("kernel-xen"))
|| (! Mode::normal () && Pkg::IsSelected ("xen")
&& Pkg::IsSelected ("kernel-xen")));
y2milestone("ret: %1", ret);
return ret;
}
/**
* Function check if trusted grub is selected
* or installed return true if is selected/installed
* and add trusted_grub to globals
* @return boolean true if trusted grub is selected/installed
*/
global boolean isTrustedGrub ()
{
boolean ret = false;
if (Mode::normal ())
{
if (Pkg::IsProvided ("trustedgrub") || Package::Installed("trustedgrub"))
{
ret = true;
globals["trusted_grub"] = "true";
}
} else {
if (Pkg::IsSelected ("trustedgrub"))
{
ret = true;
globals["trusted_grub"] = "true";
}
}
return ret;
}
/**
* Get the size of memory for XEN's domain 0
* @return the memory size in kB
*/
global integer Dom0MemorySize () {
list<map> memory = (list<map>) SCR::Read(.probe.memory);
y2milestone("memory: %1", memory);
integer memory_size = 0;
foreach(map info, memory, {
// internal class, main memory
if (info["class_id"]:0 == 257 && info["sub_class_id"]:0 == 2)
{
list<map> minf = info["resource", "phys_mem"]:[];
foreach(map i, minf, {
memory_size = memory_size + i["range"]:0;
}
);
}
}
);
// size in kB lowered 64 MB for XEN itself
memory_size = memory_size / 1024 - (64 * 1024);
y2milestone ("Memory size for XEN domain 0: %1", memory_size);
return memory_size;
}
/**
* Create section for linux kernel
* @param title string the section name to create (untranslated)
* @return a map describing the section
*/
global map<string,any> CreateLinuxSection (string title) {
map<string,any> ret = $[
"name" : translateSectionTitle (title),
"original_name" : title,
"type" : "image",
"__auto" : true,
"__changed" : true,
];
if (title == "memtest86") {
if (MemtestPresent ()) {
ret["image"] = "/boot/memtest.bin";
ret["__devs"] = [BootStorage::BootPartitionDevice];
return ret;
}
else {
return $[];
}
}
string resume = BootArch::ResumeAvailable ()
? getLargestSwapPartition ()
: "";
// try to use label or udev id for device name... FATE #302219
if ((resume != "") && (resume != nil))
resume = BootStorage::Dev2MountByDev(resume);
// FIXME:
// This only works in the installed system (problem with GetFinalKernel()),
// in all other cases we use the symlinks.
string kernel_fn = "";
string initrd_fn = "";
if (Mode::normal ()) {
// Find out the file names of the "real" kernel and initrd files, with
// version etc. pp. whatever (currently version-flavor) attached.
// FIXME: also do this for xen and xenpae kernels as found below
//
// Note: originally, we wanted to find out the kernel file names during
// installation proposal when the files are not yet installed. But not
// all the necessary interfaces work at that time. Now, this variant is
// only run in the "running system", and could as well look at the
// installed files.
//
// First of all, we have to initialize the RPM database
Pkg::TargetInit ( "/", // installed system
false ); // don't create a new RPM database
// Then, get the file names in the "selected" kernel package,
string kernel_package = Kernel::ComputePackage();
list<string> files = Pkg::PkgGetFilelist( kernel_package, `installed );
y2milestone ("kernel package %1 has these files: %2", kernel_package, files);
// then find the first file that matches the arch-dependent kernel file
// name prefix and the initrd filename prefix.
string kernel_prefix = "/boot/" + Kernel::GetBinary ();
string initrd_prefix = "/boot/initrd";
list<string> files_filtered = filter (string file, files, {
return ( substring(file, 0, size(kernel_prefix)) == kernel_prefix );
});
// Sort the filtered files, thus the image strings by length, the big ones
// at the beginning, the small ones at the end of the list.
// So, the first element of the sorted list files_filtered is the image string
// containing the version and flavor.
files_filtered = sort ( string kbig, string ksmall, files_filtered, ``(
size(kbig) > size(ksmall) ) );
kernel_fn = (files_filtered[0]:"");
files_filtered = filter (string file, files, {
return substring(file, 0, size(initrd_prefix)) == initrd_prefix ;
});
// Sort the filtered files, thus the initrd strings by length, the big ones
// at the beginning, the small ones at the end of the list.
// So, the first element of the sorted list files_filtered is the initrd string
// containing the version and flavor.
files_filtered = sort ( string ibig, string ismall, files_filtered, ``(
size(ibig) > size(ismall) ) );
initrd_fn = (files_filtered[0]:"");
if ((kernel_fn == "") || (kernel_fn == nil))
kernel_fn = "/boot/vmlinuz";
if ((initrd_fn == "") || (initrd_fn == nil))
initrd_fn = "/boot/initrd";
// read commandline options for kernel
list<string> cmd = (list<string>) SCR::Read(.proc.cmdline);
any vga = nil;
// trying to find "vga" option
foreach ( string key, cmd,
{
if (issubstring(key, "vga="))
vga = key;
y2milestone("key: %1", key);
});
y2milestone("vga from command line: %1", vga);
list <string> mode =[];
// split vga=value
if ((vga != nil) && (vga != ""))
mode = splitstring(tostring(vga), "=");
string vgamode =nil;
// take value if exist
if ((size(mode)>1) && (mode[0]:"" == "vga"))
vgamode = mode[1]:nil;
// add value of vga into proposal (if exist)
if ((vgamode != nil) && (vgamode != ""))
{
ret["vgamode"] = vgamode;
y2milestone("vga mode: %1", vgamode);
}
} else {
// the links are shown in the proposal; at the end of an installation,
// in bootloader_finish, they will be resolved to the real filenames
kernel_fn = "/boot/" + Kernel::GetBinary ();
initrd_fn = "/boot/initrd";
}
// done: kernel_fn and initrd_fn are the results
y2milestone ("kernel_fn: %1 initrd_fn: %2", kernel_fn, initrd_fn);
ret = (map <string, any>)union (ret, $[
"image" : kernel_fn,
"initrd" : initrd_fn,
// try to use label or udev id for device name... FATE #302219
"root" : BootStorage::Dev2MountByDev(BootStorage::RootPartitionDevice),
"append" : (title == "failsafe")
? BootArch::FailsafeKernelParams ()
: BootArch::DefaultKernelParams (resume),
"__devs" : [BootStorage::BootPartitionDevice, BootStorage::RootPartitionDevice],
]);
if (BootArch::VgaAvailable () && Kernel::GetVgaType () != "")
{
// B#352020 kokso: - Graphical failsafe mode
//if (title == "failsafe")
// ret["vga"] = "normal";
//else
ret["vgamode"] = Kernel::GetVgaType ();
// B#352020 end
}
if (title == "xen")
{
ret["type"] = "xen";
ret["xen_append"] = "";
ret["xen"] = "/boot/xen.gz";
ret["image"] = "/boot/" + Kernel::GetBinary () + "-xen";
ret["initrd"] = "/boot/initrd-xen";
}
return ret;
}
// generic versions of bootloader-specific functions
/**
* Export bootloader settings to a map
* @return bootloader settings
*/
global define map Export () {
map exp = $[
"global": remapGlobals(globals),
"sections" : remapSections(sections),
"device_map" : BootStorage::remapDeviceMap(BootStorage::device_mapping),
];
if ( ! ( loader_type == "grub" ) ) {
exp["repl_mbr"] = repl_mbr;
exp["activate"] = activate;
}
return exp;
}
/**
* Import settings from a map
* @param settings map of bootloader settings
* @return boolean true on success
*/
global define boolean Import (map settings) {
globals = settings["global"]:$[];
sections = settings["sections"]:[];
// FIXME: for grub, repl_mbr is replaced by globals["generic_mbr"]; same
// for activate; remove the following when no bootloader uses these
// variables any more
if ( ! ( loader_type == "grub" ) ) {
repl_mbr = settings["repl_mbr"]:false;
activate = settings["activate"]:false;
}
BootStorage::device_mapping = settings["device_map"]:$[];
return true;
}
/**
* Read settings from disk
* @param reread boolean true to force reread settings from system
* @param avoid_reading_device_map do not read new device map from file, use
* internal data
* @return boolean true on success
*/
global boolean Read (boolean reread, boolean avoid_reading_device_map) {
string bl = getLoaderType (false);
if (bl == "none")
return true;
InitializeLibrary (reread, bl);
if (reread)
{
BootCommon::ReadFiles (avoid_reading_device_map);
}
sections = GetSections ();
globals = GetGlobal ();
isTrustedGrub ();
BootStorage::device_mapping = GetDeviceMap ();
read_default_section_name = "";
foreach (map<string,any> s, sections, {
if (s["original_name"]:"" == "linux"
&& read_default_section_name == "")
{
read_default_section_name = s["name"]:"";
}
});
// convert device names in device map to the kernel device names
BootStorage::device_mapping = mapmap (string k , string v, BootStorage::device_mapping, {
// if we update from version 9 (SLES9), first convert old-style persistent
// device names to new-style persistent device names ("p1" -> "-part1")
// NOTE: this is idempotent; but other device name translation
// (e.g. libata migration) is not, so it will be done later
if (Mode::update () && installed_version["major"]:0 == 9) {
k = Storage::SLES9PersistentDevNames(k);
y2milestone( "devmap: dev name after SLES9 persistent dev name translation: %1", k);
}
return $[BootStorage::Dev2MountByDev(k) : v];
});
// convert custom boot device names in globals to the kernel device names
// also, for legacy bootloaders like LILO that still pass device names,
// convert the stage1_dev
globals = mapmap (string k , string v, globals, {
if ( k == "stage1_dev" || regexpmatch(k, "^boot_.*custom$" ) ) {
// see comments above
if (Mode::update () && installed_version["major"]:0 == 9) {
v = Storage::SLES9PersistentDevNames(v);
y2milestone( "globals: dev name after SLES9 persistent dev name translation: %1", v);
}
return $[k : BootStorage::Dev2MountByDev(v)];
} else {
return $[k : v];
}
});
// convert root device names in sections to kernel device names, if
// possible
sections = maplist (map<string,any> s, sections, {
string rdev = s["root"]:"";
// see comments above
if (Mode::update () && installed_version["major"]:0 == 9) {
rdev = Storage::SLES9PersistentDevNames(rdev);
y2milestone( "sections: dev name after SLES9 persistent dev name translation: %1", rdev);
}
// bnc#533782 - after changing filesystem label system doesn't boot
if (s["append"]:"" != "")
s["append"] = remapResume(s["append"]:"",true);
s["root"] = BootStorage::Dev2MountByDev(rdev);
return s;
});
return true;
}
/**
* Reset bootloader settings
* @param init boolean true to repropose also device map
*/
global define void Reset (boolean init) {
sections = [];
globals = $[];
// DetectDisks ();
repl_mbr = false;
activate = false;
activate_changed = false;
removed_sections = [];
was_proposed = false;
if (init)
{
if (getLoaderType (false) == "grub")
BootStorage::ProposeDeviceMap ();
}
}
/**
* Propose bootloader settings
*/
global void Propose () {
y2error ("No generic propose function available");
}
/** bnc# 346576 - Bootloader configuration doesn't work for serial output
* Function check if settings need to remove gfxmenu
*
* @return boolean - true if gfxmenu needs to be removed
*/
boolean removeGFXMenu ()
{
if ((globals["trusted_grub"]:"" == "true") && (haskey(globals, "gfxmenu")))
{
y2milestone("Remove gfxmenu -> selected trusted grub");
return true;
}
if ((globals["serial"]:nil != "") && (globals["serial"]:nil != nil))
{
y2milestone("Remove gfxmenu -> defined serial console");
return true;
}
if (globals["gfxmenu"]:"" == "none")
{
y2milestone("Remove gfxmenu -> disabled gfxmenu");
return true;
}
return false;
}
/** bnc #390659 - autoyast bootloader config: empty settings are ignored (memtest)
*
* Check if sections inlcude section for memtest
* if yes delete all unnecessary keys like initrd, vgamode, append...
*/
void checkMemtest ()
{
list<map<string,any> > out = [];
foreach(map<string,any> s, sections,
{
if (search(s["image"]:"","memtest") != nil)
{
map<string,any> tmp_s = $[];
tmp_s["image"] = s["image"]:"";
tmp_s["original_name"] = s["original_name"]:"";
tmp_s["name"] = s["name"]:"";
tmp_s["__changed"] = s["__changed"]:false;
tmp_s["__auto"] = s["__auto"]:false;
tmp_s["type"] = s["type"]:"";
y2milestone("Updating memtest section from: %1 to: %2", s, tmp_s);
out = add(out, tmp_s);
} else {
out = add(out, s);
}
});
sections = out;
}
/**
* Save all bootloader configuration files to the cache of the PlugLib
* PlugLib must be initialized properly !!!
* @param clean boolean true if settings should be cleaned up (checking their
* correctness, supposing all files are on the disk)
* @param init boolean true to init the library
* @param flush boolean true to flush settings to the disk
* @return boolean true if success
*/
global boolean Save (boolean clean, boolean init, boolean flush) {
if (clean)
{
BootCommon::RemoveUnexistentSections ("", "");
BootCommon::UpdateAppend ();
BootCommon::UpdateGfxMenu ();
}
boolean ret = true;
string bl = getLoaderType (false);
InitializeLibrary (init, bl);
if (bl == "none")
return true;
if (removeGFXMenu())
globals = remove(globals, "gfxmenu");
// bnc#589433 - Install grub into root (/) partition gives error
if ((globals["boot_custom"]:nil == "") && (haskey(globals, "boot_custom")))
globals = remove(globals, "boot_custom");
// FIXME: give mountby information to perl-Bootloader (or define some
// better interface), so that perl-Bootloader can use mountby device names
// for these devices instead. Tracked in bug #248162.
// convert XEN section to linux section id running in domU
// bnc #436899
// bnc #604401 Xen para-virtualized guest boots native kernel
// I have to call it before updating of BootCommon::globals to my_globals
// bnc #604401c14
ConvertXENinDomU ();
// convert custom boot device names in globals to the device names
// indicated by "mountby"
// also, for legacy bootloaders like LILO that still pass device names,
// convert the stage1_dev
map<string,string> my_globals = mapmap (string k , string v, globals, {
if ((k == "stage1_dev") || (regexpmatch(k, "^boot_.*custom$" )))
return $[k : BootStorage::Dev2MountByDev(v)];
else
return $[k : v];
});
// convert device names in device map to the device names indicated by
// "mountby"
y2milestone ("device map before mapping %1", BootStorage::device_mapping);
map<string,string> my_device_mapping =
mapmap (string k , string v, BootStorage::device_mapping, {
return $[BootStorage::Dev2MountByDev(k) : v];
});
y2milestone ("device map after mapping %1", my_device_mapping);
if (VerifyMDArray())
{
if ((enable_md_array_redundancy == false) && (haskey(my_globals, "boot_md_mbr")))
my_globals = remove(my_globals, "boot_md_mbr");
if ((enable_md_array_redundancy) && (!haskey(my_globals, "boot_md_mbr")))
my_globals["boot_md_mbr"] = BootStorage::addMDSettingsToGlobals();
} else {
if (haskey(globals, "boot_md_mbr"))
my_globals = remove(my_globals, "boot_md_mbr");
}
// add check if there is memtest and delete from memtest section
// keys like append, initrd etc...
checkMemtest ();
ret = ret && DefineMultipath(BootStorage::multipath_mapping);
ret = ret && SetDeviceMap (my_device_mapping);
ret = ret && SetSections (sections);
ret = ret && SetGlobal (my_globals);
if (flush)
{
ret = ret && CommitSettings ();
}
// write settings to /etc/sysconfig/bootloader
WriteToSysconf(false);
return ret;
}
/**
* Display bootloader summary
* @return a list of summary lines
*/
global define list<string> Summary () {
if (getLoaderType (false) == "none")
{
return [HTML::Colorize (
getLoaderName (getLoaderType (false), `summary),
"red") ];
}
map targetMap = Storage::GetTargetMap ();
map boot_target = targetMap[loader_device]:$[];
string target_name = "";
if (boot_target == $[])
{
target_name = loader_device;
if (target_name == "mbr_md")
{
list<string> mbrs = maplist (string d, integer id,
Md2Partitions (BootStorage::BootPartitionDevice),
{
map p_dev = Storage::GetDiskPartition (d);
return p_dev["disk"]:"";
});
// summary part, %1 is a list of device names
target_name = sformat (_("Master boot records of disks %1"),
mergestring (mbrs, ", "));
}
}
else
{
target_name = boot_target["name"]:"disk";
}
target_name = AddMbrToDescription (target_name, loader_device);
list<string> result = [];
// summary text, %1 is bootloader name (eg. LILO)
result = add (result, sformat (_("Boot Loader Type: %1"),
getLoaderName (getLoaderType (false), `summary)));
// summary text, location is location description (eg. /dev/hda)
result = add (result, sformat (_("Location: %1"), target_name));
list<string> sects = [];
foreach (map<string,any> s, sections, {
string title = s["name"]:"";
// section name "suffix" for default section
string def = title == globals["default"]:"" ? _(" (default)") : "";
sects = add (sects, String::EscapeTags (sformat ("+ %1%2", title, def)));
});
// summary text. %1 is list of bootloader sections
result = add (result, sformat (_("Sections:<br>%1"),
mergestring (sects, "<br>")));
if (loader_device == "/dev/null")
// summary text
result = add (result, _("Do not install boot loader; just create
configuration files"));
return result;
}
/**
* Update read settings to new version of configuration files
*/
global define void Update () {
y2debug ("No generic update function available");
}
/**
* Write bootloader settings to disk
* @return boolean true on success
*/
global define boolean Write () {
y2error ("No generic write function available");
return false;
}
// end of generic versions of bootloader-specific functions
//-----------------------------------------------------------------------------
// common functions start
// bootloader type handling functions
/**
* Set attributes of specified bootloader to variable containing
* attributes of currently used bootloader, call its initializer
* @param loader_type string loader type to initialize
*/
global define void setCurrentLoaderAttribs (string loader_type) {
y2milestone ("Setting attributes for bootloader %1", loader_type);
// testsuite hack
if (Mode::test ())
return;
if (loader_type == nil)
{
y2error ("Setting loader type to nil, this is wrong");
return;
}
// FIXME: this should be blInitializer in switcher.ycp for code cleanness
// and understandability
if (bootloader_attribs[loader_type, "initializer"]:nil != nil)
{
y2milestone ("Running bootloader initializer");
void () toEval = (void ()) (bootloader_attribs[loader_type, "initializer"]:nil);
toEval ();
y2milestone ("Initializer finished");
}
else
{
y2error ("No initializer found for >>%1<<", loader_type);
current_bootloader_attribs = $[];
}
current_bootloader_attribs = (map<string, any>) union (
current_bootloader_attribs,
(map<string, any>) eval (bootloader_attribs[loader_type]:$[])
);
}
/**
* Check whether loader with specified name is supported
* @param loader string name of loader to check
* @return string the loader name if supported, "none" otherwise
*/
string SupportedLoader (string loader) {
if (contains (bootloaders, loader))
return loader;
return "none";
}
/**
* Get currently used bootloader, detect if not set yet
* @param recheck boolean force checking bootloader
* @return string botloader type
*/
global define string getLoaderType (boolean recheck) {
if ((! recheck) && (loader_type != nil))
return loader_type;
// read bootloader to use from disk
if (Mode::update () || Mode::normal () || Mode::repair ())
{
loader_type = (string)SCR::Read (.sysconfig.bootloader.LOADER_TYPE);
if (loader_type != nil && loader_type != "")
{
if (loader_type == "s390")
loader_type = "zipl";
if (loader_type == "lilo" && Arch::ppc ())
loader_type = "ppc";
y2milestone ("Sysconfig bootloader is %1, using", loader_type);
loader_type = SupportedLoader (loader_type);
y2milestone ("Sysconfig bootloader is %1, using", loader_type);
setCurrentLoaderAttribs (loader_type);
return loader_type;
}
if (Mode::update ())
{
// FIXME: this is extremely broken, no arch specifica here !!
if (Arch::i386 ())
{
// no sysconfig variable -> old version installed -> use LILO
loader_type = "lilo";
loader_type = SupportedLoader (loader_type);
setCurrentLoaderAttribs (loader_type);
return loader_type;
}
}
}
// detect bootloader
loader_type = (string)SCR::Read (.probe.boot_arch);
if (loader_type == "s390")
loader_type = "zipl";
y2milestone ("Bootloader detection returned %1", loader_type);
// lslezak@: Arch::is_xenU() returns true only in PV guest
if (Arch::is_uml () || Arch::is_xenU())
{
// y2milestone ("Not installing any bootloader for UML/Xen PV");
// loader_type = "none";
// bnc #380982 - pygrub cannot boot kernel
// added installation of bootloader
y2milestone ("It is XEN domU and the bootloader should be installed");
}
if ((Arch::i386() || Arch::x86_64()) && Linuxrc::InstallInf("EFI") == "1")
{
loader_type = "elilo";
}
loader_type = SupportedLoader (loader_type);
y2milestone ("Detected bootloader %1", loader_type);
setCurrentLoaderAttribs (loader_type);
return loader_type;
}
/**
* set type of bootloader
* @param bootloader string type of bootloader
*/
global define void setLoaderType (string bootloader) {
if (bootloader == nil)
{
y2milestone ("Resetting the loader type");
loader_type = nil;
}
y2milestone ("Setting bootloader to >>%1<<", bootloader);
if (bootloader != nil
&& contains(bootloaders, bootloader)
&& ! Mode::test ())
{
// added kexec-tools fate# 303395
// if kexec option is equal 0 or running live installation
// doesn't install kexec-tools
list<string> bootloader_packages =[];
if ((! Mode::live_installation())
&& (Linuxrc::InstallInf ("kexec_reboot") != "0"))
{
bootloader_packages = bootloader_attribs[bootloader, "kexec-tools", "required_packages"]:[];
bootloader_packages = add(bootloader_packages, "kexec-tools");
} else {
bootloader_packages = bootloader_attribs[bootloader, "required_packages"]:[];
}
//FIXME: solve problem with installing bootloader
// it should be split and designed for each module (bootloader)
if ((bootloader == "grub") || (bootloader == "lilo") || (bootloader == "elilo"))
bootloader_packages = add(bootloader_packages, bootloader);
else if (bootloader == "ppc")
bootloader_packages = add(bootloader_packages, "lilo");
else if (bootloader == "zipl")
bootloader_packages = add(bootloader_packages, "s390-tools");
if (globals["trusted_grub"]:"" == "true")
{
bootloader_packages = bootloader_attribs[bootloader, "trustedgrub", "required_packages"]:[];
if (contains(bootloader_packages, "grub"))
bootloader_packages = filter(string key, bootloader_packages, {return (key !="grub"); });
bootloader_packages = add(bootloader_packages, "trustedgrub");
}
// don't configure package manager during autoinstallation preparing
if (Mode::normal () && (! (Mode::config () || Mode::repair ())))
{
y2milestone("Install packages :%1", bootloader_packages);
PackageSystem::InstallAll (bootloader_packages);
}
else if (Stage::initial () )
{
boolean pkg_added = false;
foreach (string p, bootloader_packages, {
y2milestone("Select bootloader package: %1", p);
PackagesProposal::AddResolvables ("yast2-bootloader", `package, [p]);
pkg_added = true;
});
}
}
else if (! Mode::test ())
{
y2error ("Unknown bootloader");
}
loader_type = bootloader;
if (loader_type != nil)
setCurrentLoaderAttribs (loader_type);
y2milestone ("Loader type set");
}
/**
* List bootloaders available for configured architecture
* @return a list of bootloaders
*/
global define list<string> getBootloaders () {
if (Mode::config ())
{
return ["grub", "lilo", "elilo", "zipl", "ppc", "default", "none"];
}
list<string> ret = [
getLoaderType (false),
(string)SCR::Read (.probe.boot_arch)
];
if (Arch::i386 () || Arch::x86_64 ())
{
ret = (list<string>)merge (ret, ["lilo", "grub"]);
if (Arch::x86_64 ())
ret = (list<string>)merge (ret, ["elilo"]);
}
// in order not to display it twice when "none" is selected
ret = filter (string l, ret, {
return l != "none";
});
ret = toset (ret);
ret = add (ret, "none");
return ret;
}
/**
* Search for section passed
* @return integer index number
*/
global define integer Section2Index (string section_name)
{
integer index = -1;
integer sectnum = -1;
foreach (map<string,any> s, BootCommon::sections, {
index = index + 1;
if (s["name"]:"" == section_name)
sectnum = index;
});
y2milestone ("ret: %1", sectnum);
return sectnum;
}
/** FATE#305008: Failover boot configurations for md arrays with redundancy
* Verify if proposal includes md array with 2 diferent disks
*
* @return boolean true if there is md array based on 2 disks
*/
global boolean VerifyMDArray ()
{
boolean ret = false;
if (haskey(globals, "boot_md_mbr"))
{
string md_array = globals["boot_md_mbr"]:"";
list<string> disks = splitstring(md_array,",");
disks = filter(string v, disks, {return (v !="");});
if (size(disks) == 2)
{
y2milestone("boot_md_mbr includes 2 disks: %1", disks);
ret = true;
}
}
return ret;
}
}
/*
* Local variables:
* mode: ycp
* mode: font-lock
* mode: auto-fill
* indent-level: 4
* fill-column: 78
* End:
*/
ACC SHELL 2018