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
/
OSRBoot.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
38KB
|
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