home *** CD-ROM | disk | FTP | other *** search
Text File | 2006-11-29 | 36.8 KB | 1,393 lines |
- /**
- * File: OSRBoot.ycp
- * Module: repair
- * Summary: Bootloader checks
- * Authors: Johannes Buchhold <jbuch@suse.de>
- *
- * $Id: OSRBoot.ycp 25045 2005-08-18 12:06:28Z jsuchome $
- *
- * Provide osr mode information.
- */
-
- {
-
- module "OSRBoot";
-
- import "Storage";
- import "StorageDevices";
- import "Report";
- import "Installation";
- import "Mode";
- import "Popup";
- import "Wizard";
-
- import "Bootloader";
- import "BootCommon";
- import "Initrd";
- import "Kernel";
-
- import "OSRSystem";
- import "OSRLogFile";
- import "OSRExecute";
- import "OSRPkg";
- import "OSRPopup";
- import "OSRCommon";
-
- textdomain "repair";
-
- include "repair/bootloader_routines.ycp";
-
- /**
- * Configuration files needed by every boot loader
- */
- global map needed_config_files = $[
- "modules" : "/etc/modprobe.conf",
- "initrd" : "/etc/sysconfig/kernel",
- "bootleader" : "/etc/sysconfig/bootloader"
- ];
-
- /**
- * Boot loader package name and required version
- */
- map bootloader_packages = $[
- "lilo" : [
- $[
- "pkgname" : "lilo",
- "pkgversion" : "22.3.2-32"
- ],
- $[
- "pkgname" : "gfxboot",
- "pkgversion" : "1.9-34"
- ]
- ],
- "grub" : [
- $[
- "pkgname" : "grub",
- "pkgversion" : "0.92-69"
- ]
- ],
- "silo" : [], //"SILO",
- "milo" : [], //"MILO",
- "aboot" : [], //"aboot",^
- "elilo" : [], //"ELILO",
- "mips" : [], //"dvh",
- "s390" : [], //"zipl",
- "ppc" : [] //"boot loader"
- ];
-
- // function prototypes
- define boolean check_lilo_config();
- define boolean check_grub_config();
- global define symbol repair_grub_config();
-
- /**
- * Check and repair define for every support boot loader
- */
- map bootloader_config_check = $[
- "lilo" : $[
- "config_check" : check_lilo_config,
- "config_repair" : repair_grub_config,
- "config_file" : "/etc/lilo.conf"
- ],
- "grub" : $[
- "config_check" : check_grub_config,
- "config_repair" : repair_grub_config,
- "config_file" : "/etc/grub.conf",
- "device_map" : "/boot/grub/device.map",
- "stage1" : "/boot/grub/stage1",
- "stage2" : "/boot/grub/stage2",
- "menu" : "/boot/grub/menu.lst"
- ],
- "silo" : $[], //"SILO",
- "milo" : $[], //"MILO",
- "aboot" : $[], //"aboot",
- "elilo" : $[], //"ELILO",
- "mips" : $[], //"dvh",
- "s390" : $[], //"zipl",
- "ppc" : $[] //"boot loader"
- ];
-
- list valid_grub_menu_enties = [];
-
- list grub_generally = [
- "bootp" ,
- "color" ,
- "device" ,
- "dhcp" ,
- "hide" ,
- "ifconfig" ,
- "pager" ,
- "partnew" ,
- "parttype" ,
- "password" ,
- "rarp" ,
- "serial" ,
- "setkey" ,
- "terminal" ,
- "tftpserver" ,
- "unhide" ,
- "gfxmenu" ,
- ];
-
- list grub_menu_only = [
- "default" ,
- "fallback" ,
- "hiddenmenu" ,
- "timeout" ,
- "title"
- ];
-
- list grub_menu = [
- "blocklist" ,
- "boot" ,
- "cat" ,
- "chainloader" ,
- "cmp" ,
- "configfile" ,
- "debug" ,
- "displayapm" ,
- "displaymem" ,
- "embed" ,
- "find" ,
- "fstest" ,
- "geometry" ,
- "halt" ,
- "help" ,
- "impsprobe" ,
- "initrd" ,
- "install" ,
- "ioprobe" ,
- "kernel" ,
- "lock" ,
- "makeactive" ,
- "map" ,
- "md5crypt" ,
- "module" ,
- "modulenounzip" ,
- "pause" ,
- "quit" ,
- "reboot" ,
- "read" ,
- "root" ,
- "rootnoverify" ,
- "savedefault" ,
- "setup" ,
- "testload" ,
- "testvbe" ,
- "uppermem" ,
- "vbeprobe"
- ];
-
- /**
- * Default settings for /etc/grub.conf
- */
- map grub_conf_defaults = $[ "discswitch" : "d",
- "addr" : "0x8000"];
-
- /**
- * File for backup bootloader settings
- */
- string config_backup_path = "/bootloader";
- boolean backup_created = false;
-
- /**
- * Error message if the check defines found an error
- */
- string error_message = "";
-
- /**
- * Help text if the check defines found an error
- */
- string help_text = "";
-
- /**
- * The name of the boot loader
- */
- string bootloader = "";
-
- /**
- * A list with all invalid configuration files.
- */
- list<string> invalid_config_files = [];
-
- /**
- * A list of all not installed boot loader packages
- */
- global list<string> missing_packages = [];
-
- /**
- * The root mount point.
- */
- global string root_mountpoint = Installation::destdir;
-
- /**
- * The root device e.g.: /dev/hda2
- */
- global string root_device = "";
-
- /**
- * The boot device e.g.: /dev/hda1
- */
- global string boot_device = "";
-
- global boolean bootloader_error_found = false;
-
- global list<string> not_valid_files = [];
-
- global list current_initrd_modules = [];
-
-
-
- /**
- * Reset module settings.
- **/
- global define void Reset()``{
- not_valid_files = [];
- bootloader_error_found = false;
- invalid_config_files = [];
- boot_device = "";
- root_device = "";
- bootloader = "";
- missing_packages = [];
- help_text = "";
- error_message = "";
- current_initrd_modules = [];
- //not backup_created
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Package data access functions
- ////////////////////////////////////////////////////////////////////////////
-
- /**
- * The minimal package version of a package.
- */
- define string RequiredPackageVersion(string bootloader, string package )``{
- map package_data = (map)
- find (map pkgdata, bootloader_packages[bootloader]:[],
- ``( pkgdata["pkgname"]:"" == package));
-
- if (package_data == nil || package_data == $[])
- {
- y2error("package version not found");
- return "";
- }
- else
- {
- return package_data["pkgversion"]:"";
- }
- }
-
- /**
- * Return a list of strings with all required boot loader packages with the current
- * and the required version.
- */
- global define list<string> PackageVersionStrings(string bootloader, list<string> packages )``{
- list<string> ret = [];
- foreach(string package, packages, ``{
- string package_version = package;
- if (!Mode::test ())
- {
- package_version = package_version + " current version: " +
- Pkg::PkgVersion(package) + " required version: " +
- RequiredPackageVersion(bootloader, package);
- }
- ret = add(ret, package_version );
- });
- return ret;
- }
-
- /**
- * Return all needed packages of a boot loader.
- */
- global define list<string> BootloaderPackages(string bootloader )``{
- return maplist(map pkgdata, bootloader_packages[bootloader]:[], ``( pkgdata["pkgname"]:"" ));
- }
-
- /**
- * Compares the two specified version numbers. Each version number has to be a string
- * of the form "21.6-34", "34.4.3", ...
- *
- * API function.
- * See the testsuite.
- *
- * @param string version_1 The first version-number as string.
- * @param string version_2 The second version-number as string.
- * @return boolean True if the first version number is newer than the second one.
- * @example if (!OSRVersionIsHigherOrEqual("21.6", "22.3")) y2error("Something's wrong here.")
- */
- global define boolean VersionIsHigherOrEqual( string version_1, string version_2 ) ``{
-
- list<string> v_1 = [];
- list<string> v_2 = [];
- integer n_1 = 0;
- integer n_2 = 0;
- integer index = 0;
- integer max = 0;
-
- // split the version-strings at the dots- and minus-characters "24.5.6" -> ["24", "5", "6"]
- v_1 = splitstring(version_1, ".-");
- v_2 = splitstring(version_2, ".-");
-
- // select the smaller one of the two numbers
- if (size(v_1) < size(v_2))
- {
- max = size(v_1);
- }
- else
- {
- max = size(v_2);
- }
-
- // iterate the splitted version-numbers
- while(index < max)
- {
- n_1 = tointeger (v_1[index]:"0");
- n_2 = tointeger (v_2[index]:"0");
-
- if (n_1 > n_2)
- {
- return true;
- }
- else if (n_1 < n_2)
- {
- return false;
- }
- index = index + 1;
- }
-
- // if the splitted numbers were all equal, look if the first version-number
- // consits of more parts than the second one
- return (size(v_1) >= size(v_2));
- };
-
-
- /**
- * build the help text with the package summary
- * for all specified packages
- */
- define string build_packages_help(list<string> missing_packages )``{
- string help_text = "";
- foreach(string package, missing_packages,``{
- help_text = help_text +sformat("<b>%1</b><br>%2<br>",package, Pkg::PkgSummary(package));
- });
- return help_text;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Checking sysconfig fils and boot loader packages
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- /**
- * Check the main config file for boot loader and kernel initrd
- */
- global define boolean CheckSysconfigFiles(string root)``{
-
- if( root != "" ) root_mountpoint = root;
-
- // TODO check if one module is needed at least
- string r1 = (string) SCR::Read (.sysconfig.kernel.INITRD_MODULES);
- if( r1 == nil ) not_valid_files = add(not_valid_files, needed_config_files["initrd"]:"");
-
- r1 = (string) SCR::Read (.sysconfig.bootloader.LOADER_TYPE);
- if( r1 == nil || r1 == "" ) not_valid_files = add(not_valid_files, needed_config_files["bootloader"]:"");
-
- integer r2 = Mode::test () ? 0 : (integer) WFM::Execute(.local.bash,
- sformat("/usr/bin/test -f %1%2",
- root_mountpoint, needed_config_files["modules"]:""));
- if (r2 != 0)
- {
- not_valid_files = add (not_valid_files,
- needed_config_files["modules"]:"");
- }
-
- if( size( not_valid_files ) > 0 )
- {
- bootloader_error_found = true;
- y2error("checking the sysconfig file found error");
- }
- return size( not_valid_files ) == 0;
- }
-
-
- /**
- * Check boot loader packages.
- * @param what = "installed" if all packages are installed
- * what = "version" if all packages have the required version
- * what = "verify" if all packages are not damaged
- */
- global define boolean CheckLoaderPackages(string loader, string root, string what )``{
-
- if( loader != "") bootloader = loader;
- if( root != "") root_mountpoint = root;
-
- missing_packages = [];
-
- OSRPkg::OpenPkg( root_mountpoint );
-
- // check all needed packages
- foreach(string package, BootloaderPackages( bootloader ), ``{
-
- if( what == "installed" )
- {
- if(!Mode::test () && ! Pkg::IsProvided ( package ) ) {
- missing_packages = add(missing_packages, package);
- }
- else {
- y2milestone("installed package %1", package );
- }
- // TODO check dependencies
- }
- else if ( what == "verify" )
- {
- //Pkg::XXX not support
- string command = sformat("/bin/rpm -V -r\"%1\" %2", root_mountpoint, package);
-
- if ( ! OSRExecute::CommandOutput(.local.bash_output, command)) {
- missing_packages = add(missing_packages, package);
- }
- else {
- y2milestone("package %1 verified", package);
- }
- }
- else if ( what == "version" )
- {
- if (!Mode::test () &&
- !VersionIsHigherOrEqual (Pkg::PkgVersion (package),
- RequiredPackageVersion(bootloader, package)))
- {
- missing_packages = add(missing_packages, package );
- }
- else {
- y2milestone("package %1 version is ok.", package);
- }
- }
- else {
- y2error("CheckLoaderPackages what is not valid");
- }
-
- });
-
- if ( size(missing_packages) > 0 )
- {
- bootloader_error_found = true;
- y2error(" package check found error");
- }
- return size(missing_packages) == 0;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Install missing or damaged boot loader packages
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- /**
- * Install all missing package if the user accept.
- */
- global define symbol InstallLoaderPackage(string loader, string root, string install_reason )``{
-
- if( loader != "" ) bootloader = loader;
- if( root != "" ) root_mountpoint = root;
-
- string help_text = build_packages_help( missing_packages );
- // error message: %1 is explanation, %2 is list of packages
- string error_message = sformat(_("
- %1
-
- %2
-
- Press Repair to install these packages.
- "),install_reason, mergestring( missing_packages, "\n" ));
-
-
- if( OSRPopup::Repair(_("Boot Loader Package Missing"), error_message, help_text)) {
-
- OSRPkg::root_mountpoint = root;
- OSRPkg::missing_packages = missing_packages;
- return OSRPkg::InstallMissing(false);
- }
- else
- {
- y2milestone(" installing missing loader packages was canceled");
- return `cancel;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Check initrd modules
- ///////////////////////////////////////////////////////////////////////////
-
- /**
- * Check the specified initrd modules.
- */
- global define boolean CheckInitrdModules(string root )``{
- if( root != "") root_mountpoint = root;
-
- string crs = (string) SCR::Read (.sysconfig.kernel.INITRD_MODULES);
- current_initrd_modules = splitstring(crs, " ");
- y2milestone("current initrd_modules %1", current_initrd_modules);
-
- list storage_initrd = Storage::GetRootInitrdModules();
- y2milestone(" found initrd modules %1",storage_initrd );
-
- //add found modules to Boot::initrdModules
- foreach(string m, (list<string>) storage_initrd, ``{
- Initrd::AddModule (m, "");
- });
-
- list<string> listed_modules = Initrd::ListModules();
- y2milestone("needed initrd_modules in Boot %1", listed_modules );
- list<string> missing = (list<string>) filter(string s, listed_modules,
- ``( !contains(current_initrd_modules, s)));
-
- // if( Mode::test () ) missing = add(missing, "reiserfs");
-
- if (size( missing ) > 0)
- {
- help_text = _("
- The variable INITRD_MODULES contains the list of modules
- to add to the initial RAM disk by calling the script mkinitrd.
- Examples are drivers for SCSI controllers, LVM, reiserfs.
- ");
- //%1 is file name, %2 is list of kernel modules
- error_message = sformat(_("
- The file %1 contains a list
- of modules to add to the initial
- RAM disk by calling the script mkinitrd.
- YaST is missing the following modules:
-
- %2
-
- Press Repair to add the missing
- modules to the initial RAM disk.
- "), needed_config_files["initrd"]:"", mergestring( missing , "\n" ));
-
-
- return false;
- }
- return true;
- }
-
-
- /**
- * Wirte initrd modules and call mkinitrd
- */
- global define symbol RepairInitrdModules()``{
- // initrd is case-sensitive
- if ( ! OSRPopup::Repair(_("initrd Modules Missing"), error_message, help_text) ) {
- return `cancel;
- }
- boolean ret = true;
- string kernel_initrd = mergestring
- ((list<string>)Initrd::ListModules(), " ");
-
- if ( ! Mode::test () )
- {
- // write INITRD_MODULES - Initrd::Write() could be used?
- SCR::Write (.sysconfig.kernel.INITRD_MODULES, kernel_initrd);
- SCR::Write (.sysconfig.kernel, nil);
-
- string destproc = "/proc";
- SCR::Execute (.target.mkdir, destproc, 0755);
- SCR::Execute (.target.mount, ["proc", destproc], "-t proc");
- ret = (0 == SCR::Execute(.target.bash, "/sbin/mkinitrd >> /var/log/YaST2/y2logmkinitrd 2>> /var/log/YaST2/y2logmkinitrd"));
- SCR::Execute (.target.umount, destproc );
- }
-
- if (! ret)
- {
- // question in a popup box
- if ( Popup::YesNo( _("Calling mkinitrd failed.
- Display the log file?
- ")))
- {
- Popup::ShowFile( _("The Output of the Script mkinitrd"), "/var/log/YaST2/y2logmkinitrd" );
- }
- }
- if( ret ) return `ok;
- else return `error;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Check the boot loader configuration files
- ////////////////////////////////////////////////////////////////////////////
-
- /**
- * Check if the boot loader conf file exists.
- */
- global define boolean ExistsConf(string loader, string root )``{
- if ( loader != "" ) bootloader = loader;
- if ( root != "" ) root_mountpoint = root;
-
- // look if the file lilo.conf exists an has a positive size
- if ( ! (SCR::Read(.target.size, bootloader_config_check[bootloader, "config_file"]:"") > 0 ))
- {
- //No conf file found
- help_text = sformat(_("
- <p>The file %1 was not found.</p>"), bootloader_config_check[bootloader, "config_file"]:"") +
-
- _("<p>The boot loader configuration file contains
- defective data. Depending on the boot loader
- type, the syntax of the configuration file
- differs. </p>
- ");
-
- error_message = _("
- The main configuration file of the boot loader was
- not found.
-
- If you changed the boot loader configuration
- manually and the system starts correctly,
- skip this dialog and continue the detection
- sequence.
- If you never changed anything affecting
- the boot loader, press Repair
- to create a new configuration file.
- ");
-
- invalid_config_files = add(invalid_config_files, bootloader_config_check[bootloader, "config_file"]:"");
- bootloader_error_found = true;
- y2error("can't find boot loader conf file");
- return false;
- }
- return true;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Check the lilo configuration file
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Check the lilo conf file.
- */
- define boolean check_lilo_config()``{
-
- // Be careful: use the mountpoint of the root partition for execution of this command!
- string command = sformat("%1/sbin/lilo -r %1 -t -v", root_mountpoint );
-
- if( OSRExecute::Command(.local.bash, command ))
- {
- return true;
- }
- else {
-
- y2error("lilo config file %1 is not valid", bootloader_config_check[bootloader, "config_file" ]:"");
-
- // help text 1/2
- help_text = _("
- <p>The command /sbin/lilo -t checks the syntax
- of the LILO boot loader configuration file.</p>
- ") +
-
- // help text 2/2
- _("<p>This command returned an error. This normally means
- your system is not bootable.
-
- It is recommended to create a new configuration
- file.</P>
- ");
-
- // error message
- error_message = _("
- The syntax of the boot loader configuration
- file is not valid.
- The configuration file contains defective
- data needed for booting the Linux system.
-
- Press Repair to generate a new
- configuration file automatically.
-
- If you are sure your configuration file
- contains no errors, press Skip.
- ");
- return false;
- }
-
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Device check.
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- /**
- * Returns false if the specified device can not
- * found in the target_map (Storage module)
- */
- define boolean exists_device(string dev_name )``{
-
- if(dev_name == "" ) return true;
-
- // if device is a floppy
- if( StorageDevices::FloppyDrives == [] || StorageDevices::FloppyDrives == nil ) StorageDevices::Probe(false);
- y2milestone("FloppyDrives %1", StorageDevices::FloppyDrives );
- map ret = find(map e, StorageDevices::FloppyDrives, ``(e["dev_orig"]:(e["dev_name"]:"") == dev_name));
- if ( ret != nil && size( ret ) > 0 ) return true;
-
- // if device is a hard disk
- map<string,map> tg = Storage::GetTargetMap();
- ret = tg[dev_name]:$[];
- if ( ret != nil && size( ret ) > 0 ) return true;
-
- // if device is a partition
- ret = Storage::GetPartition( tg, dev_name );
- if ( ret != nil && size( ret ) > 0 ) return true;
-
- // fix grub bug
- if ( substring( dev_name, 0, 7) == "/dev/fd" )
- {
- return true;
- }
-
- // device does not exists
- y2error("device with name %1 not found", dev_name);
- return false;
- }
-
- /**
- * Convert a grub device (hd0) to a lilo device name (/dev/hda1)
- * grub2Lilo can't convert floppy device.
- */
- define string grubDev2LiloDev(string grub_device )``{
-
- if ( grub_device == "")
- return "";
-
- string ret = "";
- if ( !regexpmatch(grub_device, ".fd.*"))
- {
- ret = grubDev2unixDev (grub_device);
- }
- else
- {
- ret = "/dev/" + substring(grub_device, 1, 3);
- }
- y2milestone("grubDev2unixDev converts %1 to %2", grub_device, ret );
- return ret;
- }
-
- /**
- * Check if a device (grub syntax) exist.
- */
- define boolean exists_grub_device(string grub_device )``{
-
- //"device":"(hd0)"
- if( exists_device(grubDev2LiloDev( grub_device )))
- {
- y2milestone(" device %1 exists", grub_device);
- return true;
- }
- else
- {
- y2error(" device %1 not found", grub_device);
- return false;
- }
- }
-
-
-
- //////////////////////////////////////////////////////////////////
- // grub conf file checks
- //////////////////////////////////////////////////////////////////
-
- /**
- * Check a grub device entry.
- */
- define boolean check_grub_device(string grub_device )``{
- y2milestone("check grub device: %1", grub_device);
- if ( grub_device == "") return true;
- return exists_grub_device(grub_device);
- }
-
- /**
- * Check if the root entry exists and is the expected
- */
- define boolean check_grub_root(string root ) {
-
- y2milestone("check grub root: %1", root);
-
- if (root == "") return true;
-
- if (! exists_grub_device(root)) return false;
-
- string check_dev = root_device;
-
- if( boot_device != root_device )
- {
- check_dev = boot_device;
- }
-
- if( check_dev == grubDev2LiloDev(root)) return true;
- else return false;
- }
-
- /**
- * Check the addr entry of a grub conf file.
- */
- define boolean check_grub_addr( string addr )``{
- if( addr == "" )
- {
- addr = grub_conf_defaults["addr"]:"";
- y2milestone("adrr not set - use default addr");
- }
-
- if( addr != grub_conf_defaults["addr"]:""){
- y2error("grub addr (%1) changed not default %2", addr, grub_conf_defaults["addr"]:"");
- // TODO is it a problem, that addr is different from default?
- }
- return true;
- }
-
- /**
- *
- */
- define boolean check_grub_discswitch (string discswitch)``{
-
- if (discswitch != "")
- {
- if (discswitch != grub_conf_defaults["discswitch"]:"")
- {
- y2error("grub discswitch (%1) changed not default %2",
- discswitch, grub_conf_defaults["discswitch"]:"");
- }
- }
- return true;
- }
-
- /**
- * Test if stage1 exist.
- */
- define boolean check_grub_stage1( string stage1 )``{
- if ( stage1 == "" )
- {
- stage1 = bootloader_config_check[bootloader, "stage1"]:"";
- }
- return OSRExecute::Command(.local.bash, sformat(
- "/usr/bin/test -f %1%2 -o -f %1/boot%2", root_mountpoint, stage1));
- }
-
- /**
- * Test if stage2 exist.
- */
- define boolean check_grub_stage2(string stage2)``{
- return OSRExecute::Command(.local.bash, sformat(
- "/usr/bin/test -f %1%2 -o -f %1/boot%2", root_mountpoint, stage2 ));
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // grub menu file checks
- ///////////////////////////////////////////////////////////////////////////
-
- /**
- * Checks the keys of one map.
- */
- define boolean check_grub_menu_entry_map(map entries)``{
- boolean error_found = false;
- foreach(string key, string value, (map<string,string>)entries ,``{
- if( ! contains(valid_grub_menu_enties, key ))
- {
- y2error("key -%1- not found - no valid key", key);
- error_found = true;
- }
- });
- return ! error_found;
- }
-
- /**
- * Check the keys of the specified map.
- * @param entries = $["color":"white/blue black/light-gray",
- * "default":"0", "gfxmenu":"(hd0,2)/boot/message",
- * "timeout":"8"]
- * @return true if all keys are valid
- */
- define boolean check_grub_global_options(map entries )``{
- valid_grub_menu_enties = union( grub_generally, grub_menu_only );
- return check_grub_menu_entry_map(entries);
- }
-
- /**
- * Checks all maps of the specified list.
- * @param entries = [$["initrd":"(hd0,2)/boot/initrd",
- * "kernel":"(hd0,2)/boot/vmlinuz root=/dev/hda3 vga=791", "title":"linux"],
- * error ->$["asd":"", "chainloader":"+1", "makeactive":"true", "root":"(hd1,0)", "title":"windows"],
- * $["chainloader":"+1", "root":"(fd0)", "title":"floppy"],
- * $["initrd":"(hd0,2)/boot/initrd.shipped", "kernel":"(hd0,2)/boot/vmlinuz.shipped root=/dev/hda3
- * ide=nodma apm=off acpi=off vga=normal nosmp maxcpus=0 disableapic 3", "title":"failsafe"]]
- */
- define boolean check_grub_menu_entries(list entries )``{
- valid_grub_menu_enties = union( grub_menu, grub_menu_only);
- boolean error_found = false;
- foreach(map menu, (list<map<any,any> >)entries, ``{
- error_found = ! (check_grub_menu_entry_map(menu) == false ) ? false : !error_found;
- });
- return ! error_found;
- }
-
- /**
- * reads specified section and returns values as list [$[option:$[value:..., comment:...]]]
- * @param type string sections / ""
- * @param section string
- * @return map map as described above
- */
- global define map sectOptions2Map(string loader ,string type, string section) ``{
- path p = .;
-
- if (type == "")
- {
- p = topath (loader);
- }
- else
- {
- p = add( add (topath (loader), "sections"), section);
- }
-
- list optlist = SCR::Dir(p);
-
- if (type == "")
- {
- optlist = filter(string e, (list<string>) optlist, ``(e != "sections"));
- }
-
- any value = "";
- map retval = $[ ];
-
- foreach (string e, (list<string>) optlist, ``{
- value = BootCommon::mod2ui (SCR::Read(add(p, e)));
- if (isSpecial(e))
- {
- retval = add (retval,
- e, mergestring ((list<string>)SCR::Read(add(p, e)), ","));
- }
- else
- {
- retval = add(retval, e, sformat("%1", value));
- }
- });
- return retval;
- }
-
-
- /**
- * Check the grub menu and the grub menu entries.
- */
- define boolean check_grub_menu( string menu )``{
-
- string menu_dev = "";
- string menu_path = "";
-
- if( menu == "" )
- {
- menu_path = bootloader_config_check["grub", "menu"]:"";
- }
- else {
- menu_dev = substring(menu, 0, findfirstof(menu, ")") +1 );
- menu_path = substring(menu, findfirstof(menu, ")") +1 );
- }
- y2milestone("menu_path %1, menu_dev %2, menu: %3",menu_path,menu_dev,menu);
-
- if( menu_dev != "" && ! exists_grub_device(menu_dev ) )
- {
- invalid_config_files = add(invalid_config_files, menu_path );
- y2error("grub menu device not found %1", menu);
- return false;
- }
- // TODO: get the real mountpoint for boot partition
- if(!OSRExecute::Command(.local.bash, sformat(
- "/usr/bin/test -f %1%2 -o -f %1/boot%2", root_mountpoint, menu_path)))
- {
- invalid_config_files = add(invalid_config_files, menu_path );
- y2error("grub menu file not found: %1",menu_path);
- return false;
- }
- else
- {
- // read grub menu file
- map global_options = sectOptions2Map("grub" , "", "");
- list sects = SCR::Dir(.grub.sections);
- list sections = [];
-
- foreach(string e, (list<string>) sects, ``{ sections = add(sections, sectOptions2Map("grub", "sections", e)); });
-
- // debug grub menu file
- y2milestone("options : %1", global_options );
- y2milestone("sections : %1", sections );
-
- // check keys in the grub menu file
- boolean ret = check_grub_global_options(global_options) && check_grub_menu_entries(sections);
-
- if( ! ret )
- {
- y2error("the grub menu file is not valid");
- invalid_config_files = add(invalid_config_files, menu_path );
- }
- return ret;
- }
- }
-
-
- /**
- * Check the grub device map.
- */
- define boolean check_grub_device_map()``{
-
- // TODO: get the real mountpoint for boot partition
- string grub_dir = root_mountpoint + "/boot/grub";
- if (! OSRExecute::Command(.local.bash, sformat("/usr/bin/test -d %1",grub_dir)))
- {
- y2error("grub directory does not exist");
- invalid_config_files = add(invalid_config_files, bootloader_config_check[bootloader, "device_map"]:"" );
- return false;
- }
-
- string dev_map = (string) SCR::Read(.target.string,
- bootloader_config_check[bootloader, "device_map"]:"" );
-
- if( dev_map == "" || dev_map == nil )
- {
- y2error("reading device map was not successful");
- invalid_config_files = add(invalid_config_files, bootloader_config_check[bootloader, "device_map"]:"" );
- return false;
- }
-
- list maps = filter (string e, splitstring (dev_map, "\n"), ``(e != ""));
- maps = maplist (string e, (list<string>) maps, ``{
- return filter (string f, splitstring (e, " \t"), ``(f != ""));
- });
-
- boolean error_found = false;
- foreach (list e, (list<list<any> >)maps, ``{
- if ( ! error_found )
- {
- error_found = ! exists_grub_device( e[0]:"");
- if( error_found )
- y2error("grub device map: device not found %1", e[0]:"");
- }
- if ( ! error_found )
- {
- error_found = ! exists_device (e[1]:"");
- if ( error_found )
- y2error("grub device map: device not found %1", e[0]:"");
- }
- });
-
- if ( error_found == nil || error_found )
- {
- invalid_config_files = add(invalid_config_files, bootloader_config_check[bootloader, "device_map"]:"" );
-
- return false;
- }
- return true;
- }
-
- /**
- * Check the sysntax of grub configuration files:
- * /boot/grub/device.map
- * /boot/grub/menu.lst
- * /etc/grub.conf
- */
- define boolean check_grub_config() {
-
- // check /boot/grub/device.map
- // (fd0) /dev/fd0
- // (hd0) /dev/hda
- // (hd1) /dev/hdb
- boolean grub_device_map = check_grub_device_map();
- if (!grub_device_map)
- {
- y2error("grub devide map contains errors");
- }
-
- /* systax of grub_conf:
- $[
- "addr" : "0x8000",
- "device" : "(hd0)",
- "discswitch" : true,
- "menu" : "(hd0,2)/boot/grub/menu.lst",
- "root" : "(hd0,2)",
- "s2prefix" : "--stage2=/boot/grub/stage2",
- "stage1" : "/boot/grub/stage1",
- "stage2" : "/boot/grub/stage2"]
- */
- string conf_file_contens = (string) SCR::Read(.target.string,
- bootloader_config_check[bootloader, "config_file"]:"");
-
- map grub_conf = parseGrubConf (conf_file_contens);
- y2internal ("grub_conf: %1", grub_conf);
-
- boolean embedding = false;
- if (grub_conf["command"]:"" == "setup")
- {
- embedding = true;
- y2milestone ("embedding stage 1.5 -> reduced checking");
- }
-
- readDeviceMap ();
-
- boolean grub_device = check_grub_device (grub_conf["device"]:"" );
- boolean grub_root = check_grub_root (grub_conf["root"]:"" );
- boolean grub_addr = embedding ||
- check_grub_addr (grub_conf["addr"]:"" );
- boolean grub_discheck = embedding ||
- check_grub_discswitch (grub_conf["discswitch"]:"");
- boolean grub_stage1 = embedding ||
- check_grub_stage1 (grub_conf["stage1"]:"");
- boolean grub_stage2 = embedding ||
- check_grub_stage2 (grub_conf["stage2"]:"");
- boolean grub_menu = embedding ||
- check_grub_menu (grub_conf["menu"]:"" );
-
- if ( ! grub_device )
- y2error("grub conf device entry is invalid");
- if ( ! grub_root )
- y2error("grub conf root entry is invalid");
- if ( ! grub_addr )
- y2error("grub conf addr entry is invalid");
- if ( ! grub_discheck)
- y2error("grub conf discswitch entry is invalid");
- if ( ! grub_stage1 )
- y2error("grub conf state1 is invalid");
- if ( ! grub_stage2 )
- y2error("grub conf state2 is invalid");
-
- if ( grub_menu == nil ) {
- y2error("grub menu is invalid");
- grub_menu = false;
- }
- if (grub_device && grub_root && grub_addr && grub_menu &&
- grub_discheck && grub_stage1 && grub_stage2 && grub_device_map)
- {
- return true;
- }
- else
- {
- string menu_path = grub_conf["menu"]:"";
- if (menu_path == "" || menu_path == nil)
- {
- menu_path = bootloader_config_check[bootloader, "menu"]:"";
- }
- else
- {
- menu_path = substring(menu_path , findfirstof(menu_path, ")") +1 );
- }
-
- // help text 1/4
- help_text = _("
- <p>A default GRUB installation needs three
- configuration files:</p>
- ") +
-
- sformat("<p>%1</p>", mergestring ([
- bootloader_config_check [bootloader, "device_map"]:"",
- bootloader_config_check [bootloader, "config_file"]:"",
- menu_path
- ],"<br>")) +
-
- // help text 2/4
- _("<P>The following files
- are not valid:</p>
- ") +
-
- sformat ("<p>%1</p>", mergestring (invalid_config_files, "<br>")) +
-
- // help text 3/4
- _("<p>This generally means that your system is not
- bootable.</p>
- ") +
-
- // help text 4/4
- _("<p>Creating a new boot loader
- configuration is recommended.</p>
- ");
-
- // error text
- error_message = _("
- The configuration of the boot loader
- contains errors.
-
- Press Repair to generate a new
- configuration automatically.
-
- If you are sure your configuration
- contains no errors and your system
- is bootable, press Skip.
- ");
-
- return false;
- }
- }
-
- /**
- * Check the boot loader configuration.
- */
- global define boolean CheckConfig(string loader , string root, string root_dev, string boot_dev )``{
-
- if ( loader != "" ) bootloader = loader;
- if ( root != "" ) root_mountpoint = root;
- if ( root_dev != "" ) root_device = root_dev;
- if ( boot_dev != "" ) boot_device = boot_dev;
-
- // reset settings
- error_message = "";
- help_text = "";
- invalid_config_files = [];
-
- if (!haskey (bootloader_config_check [bootloader]:$[], "config_check"))
- {
- y2error("boot loader config check not supported");
- bootloader_error_found = true;
- return false;
- }
- boolean () check_f =
- bootloader_config_check[bootloader,"config_check"]:OSRCommon::False;
- if (!Mode::test () && !check_f ())
- {
- bootloader_error_found = true;
- y2error("boot loader config check returned an error");
- return false;
- }
- return true;
- }
-
-
- /**
- * Repair a damaged grub configuration.
- */
- global define symbol repair_grub_config()``{
-
- // change root for boot loader module call - why??
- Bootloader::setLoaderType (nil);
- Bootloader::Reset();
- Bootloader::Propose(); // does not read current configuration...
- map retmap = (map)
- WFM::CallFunction ("bootloader_proposal",["AskUser", $[]]);
- symbol ret = retmap["workflow_sequence"]:`next;
-
- if( ret == `next )
- {
- Wizard::CreateDialog ();
-
- // prepare environment for saving boot loader settings
- string destproc = "/proc";
- SCR::Execute (.target.mkdir, destproc, 0755);
- SCR::Execute (.target.mount, ["proc", destproc], "-t proc");
- SCR::Execute (.target.bash, "/sbin/SuSEconfig --module bootsplash");
-
- boolean g_ret = Bootloader::Write();
- Wizard::CloseDialog();
-
- if ( g_ret )
- // message popup
- Report::Message(_("The boot loader was installed successfully."));
-
- SCR::Execute (.target.umount, "/proc");
- WFM::Execute(.local.umount, root_mountpoint + "/proc" );
- }
- return ret;
- }
-
-
- /**
- * Repair a damaged boot loader configuration.
- */
- global define symbol RepairConfig(string loader, boolean show_message )``{
- if ( loader != "" ) bootloader = loader;
- if ( show_message )
- {
- // popup headline
- if ( !OSRPopup::Repair (_("Boot Loader Error Detected"),
- error_message, help_text))
- {
- return `cancel;
- }
- }
-
- // set needed value Boot::initrdModules
- CheckInitrdModules( root_mountpoint );
- if (!haskey (bootloader_config_check [bootloader]:$[], "config_repair"))
- {
- y2error("boot loader config repair not supported");
- return `error;
- }
- symbol () repair_f = bootloader_config_check [bootloader, "config_repair"]:OSRCommon::SymbolError;
- return repair_f ();
- }
-
- /**
- * Install a new boot loader
- */
- global define symbol InstallNewLoader()``{
-
- error_message = _("
- No valid boot loader installation
- can be found. Installing
- a new boot loader is recommended.
-
- If you are sure your system boots
- correctly, it is not necessary to
- reinstall the boot loader.
-
- Otherwise, press Repair
- to install a new boot loader.
- ");
-
- help_text = _("
- <P>The boot loader is the first thing
- you should see after you turn
- on a computer with a Linux installation.
- Starting a Linux system without
- a boot loader is not possible.</P>
- ") +
-
- _("<P>If you have installed more than
- one operating system on a computer,
- the boot loader allows you to select
- which system to start.</P>
- ");
- bootloader = "";
- return RepairConfig("",true);
- }
-
-
- /**
- * Repairing configuration files.
- */
- global define symbol RepairSysconfigFiles()``{
-
- // repairing not possible
- if( contains ( not_valid_files, needed_config_files["modules"]:"") )
- {
- y2error("repairing %1 is not possible", needed_config_files["modules"]:"");
- Report::Error(sformat (_("
- The file %1 was not found.
- It cannot be recovered.
- "), needed_config_files["modules"]:""));
- return `error;
- }
-
- list<string> t_not_valid_file = filter(string file, not_valid_files, ``( file != needed_config_files["modules"]:"" ));
-
- error_message = sformat(_("
- The following configuration
- files cannot be found:
-
- %1
-
- Installing a new
- boot loader is recommended.
-
- If you are sure your system boots
- correctly, it is not necessary to
- reinstall the boot loader.
-
- Otherwise, press Repair
- to install a new boot loader.
- "), mergestring(maplist(string file, not_valid_files, ``(file)), "\n"));
-
-
- return RepairConfig(bootloader,true);
- }
- }//EOF
-