Author: juhliarik Date: Fri Jul 25 16:27:00 2008 New Revision: 49421 URL: http://svn.opensuse.org/viewcvs/yast?rev=49421&view=rev Log: - added functions for handling device.map - it is allow only 8 devices in device.map fate: #303548 - added function for remapping windows chainloader if windows is not on the first (boot) disk fate: #301994 - deleted unused code M bootloader/src/grub/misc.ycp * added function for checking windows: isWidnowsOnBootDisk() checkWidnowsSection() M bootloader/src/modules/BootGRUB.ycp * deleted unused code M bootloader/src/routines/misc.ycp * added function BootDeviceToUdevID() M bootloader/src/routines/lilolike.ycp * added function for handling device.map: ReduceDeviceMapTo8() Modified: trunk/bootloader/src/grub/misc.ycp trunk/bootloader/src/modules/BootGRUB.ycp trunk/bootloader/src/routines/lilolike.ycp trunk/bootloader/src/routines/misc.ycp Modified: trunk/bootloader/src/grub/misc.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/bootloader/src/grub/misc.ycp?rev=... ============================================================================== --- trunk/bootloader/src/grub/misc.ycp (original) +++ trunk/bootloader/src/grub/misc.ycp Fri Jul 25 16:27:00 2008 @@ -1038,8 +1038,83 @@ string ret = devpth[0]:"" + devpth[1]:""; return ret; } + + +/** FATE #301994 - Correct device mapping in case windows is installed on the second HD + * Check if chainloader section with windows is on the first disk + * + * @param map<string,any> section from BootCommon::sections + * @return boolean true if it is necessary remap section + */ +define boolean isWidnowsOnBootDisk(map<string,any> section) +{ + // check if it is windows chainloader + if ((search(tolower(section["name"]:""), "windows") != nil) + || (search(tolower(section["original_name"]:""), "windows") != nil)) + { + map p_dev = Storage::GetDiskPartition (section["chainloader"]:""); + + string disk_dev = p_dev["disk"]:""; + if (disk_dev == "") + { + y2error("trying find disk for windows chainloader failed"); + return false; + } + // find grub id in device map for chainloader device + string grub_id = BootCommon::device_mapping[disk_dev]:""; + y2milestone("Disk from windows chainloader: %1 grub id from device map: %2", disk_dev, grub_id); + + // check if disk is the first in order... + if (grub_id != "hd0") + return true; + + } + return false; } +/** FATE #301994 - Correct device mapping in case windows is installed on the second HD + * Remap and make active windows chainloader section + * if it is not on the boot (the first) disk + * @param list of sections + * @return list of sections + */ + +define list<map<string,any> > checkWidnowsSection(list<map<string,any> > sections) +{ + + // list of idexes from sections where is chainloader + // and where is necessary add remapping and makeactive + list < integer > list_index =[]; + // counter + integer index = -1; + // check all sections... + foreach(map<string,any> section, sections, + { + index = index +1; + if (haskey(section, "chainloader")) + { + y2debug("chainloader section: %1", section); + // add only indexes for update + if (isWidnowsOnBootDisk(section)) + list_index = add(list_index, index); + }; + }); + + if (size(list_index) > 0) + { + foreach (integer idx, list_index, + { + sections[idx, "remap"] = "true"; + sections[idx, "makactive"] = "true"; + } + } + + return sections; +} + + +} //last "}" + /* * Local variables: * mode: ycp Modified: trunk/bootloader/src/modules/BootGRUB.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/bootloader/src/modules/BootGRUB.y... ============================================================================== --- trunk/bootloader/src/modules/BootGRUB.ycp (original) +++ trunk/bootloader/src/modules/BootGRUB.ycp Fri Jul 25 16:27:00 2008 @@ -386,130 +386,7 @@ SCR::Execute (.target.bash, sformat ("/bin/rmdir %1", tmpdir)); } -// FIXME: remove old code: this used to parse menu.lst and device.map files -// from other linux partitions for "initial" (~ default, see -// MarkInitialSection() in perl-Bootloader) sections, and adds them to the -// current menu.lst, if none of the referenced root partition and the other -// linux partition was `destroyed (= "new, deleted or formatted"). -/* - BootCommon::InitializeLibrary (true, "grub"); - foreach (map o, other_l, { - string dev = o["device"]:""; - if (dev != "" && 0 == SCR::Execute (.target.bash, - sformat ("/bin/mount %1 %2", dev, tmpdir)) - ) - { - y2milestone ("Mounted %1", dev); - list<string> filenames = []; - foreach (string fn, [ -// not needed since there is a symlink in /boot directory -// named boot pointing to the /boot directory -// this caused bug #23346 - the file was found twice -// tmpdir + "grub/menu.lst", - tmpdir + "boot/grub/menu.lst" - ], { - if (-1 != (integer)SCR::Read (.target.size, fn)) - filenames = add (filenames, fn); - }); - y2milestone ("Found files %1", filenames); - integer count = 0; - foreach (string f, filenames, { - y2debug ("Checking file %1", f); - string fc = (string)SCR::Read (.target.string, f); - string dm = (string)SCR::Read (.target.string, - regexpsub (f, "(.*)menu.lst$", - "\1device.map")); - y2debug ("Device map file name: %1", - regexpsub (f, "(.*)menu.lst$", - "\1device.map")); - y2debug ("Device map contents: %1", dm); - -// here the old code tries to parse and import sections from the grub config file from an "other" linux partition - map<string,string> files = $[ - "/boot/grub/menu.lst" : fc, - ]; - if (dm == nil) - return; - - files["/boot/grub/device.map"] = dm; - BootCommon::InitializeLibrary (false, "grub"); - BootCommon::SetFilesContents (files); - list<map<string,string> > sects - = BootCommon::GetSections (); - y2debug ("Found sections %1", sects); - - // merge only "default" == "initial" entries, not all entries - if (merge_level == `main) - { - sects = filter (map<string,string> s, sects, { - return s["initial"]:nil != nil; - }); - } - - // now add the sections to our configuration, if they qualify - count = count + size (sects); - foreach (map<string,any> s, sects, ``{ - s = (map<string,any>)union (s, $[ - "__changed" : false, - "__auto" : true, - "__converted" : true, - ]); - // no need to translate here... - s["name"] = sformat ("%1 (%2)", - s["name"]:"", dev); - s["original_name"] = s["name"]:""; - - // this is a heuristic: if the mounted partition or the - // root partition referenced in the section is "new, - // deleted or formatted", then do not add/import the - // section - list<string> devs = [dev]; - string _d = s["root"]:""; - if (_d != nil && _d != "") - devs = add (devs, _d); - devs = (list<string>)filter (string d, devs, - ``(d != "" - && d != nil - && d != "/dev/null" && d != "false")); - devs = toset (devs); - devs = maplist (string d, devs, { - return BootCommon::UpdateDevice (d); - }); - boolean _add = true; - foreach (string _d, devs, { - if (contains (destroyed_partitions, _d)) - _add = false; - }); - - // FIXME: create a new config file section instead of - // using <s> which only shares the name/original_name - // This makes it possible to support cascaded boot - // environments in a supportable way ! - if (_add) - { - // FIXME: fallback to vmlinux and initrd symlink if - // present in the chroot environment of the other - // Linux System ... #224481 - - s["__devs"] = devs; - out = add (out, s); - } - }); - }); - - // if any sections from this device were added, it was a - // genuine linux partition: ignore it when going through the - // list of "other", non-linux partitions in the next loop below - if (count > 0) - others_ignore = add (others_ignore, dev); - SCR::Execute (.target.bash, sformat ( - "/bin/umount %1", dev)); - } - }); - SCR::Execute (.target.bash, sformat ("/bin/rmdir %1", tmpdir)); - } -*/ // Go through a list of "bootable" (aa55) primary partitions that may be // "foreign", check that it is not one of our current boot partitions and @@ -636,96 +513,6 @@ BootCommon::ProposeDeviceMap (); } - // FIXME: This code can probably be removed. perl-Bootloader sets boot_* - // flags in the globals map. That is all the UI and the proposal code deal - // with. The decision to install the bootloader stage 1 on multiple devices - // (for softraid, dmraid etc.) can be based on the information in the - // boot_{root,boot,mbr} flags and the disk, partitioning and md information - // alone. Thus, perl-Bootloader is able to do this. -/* - list<string> loader_devices = splitstring ( - BootCommon::globals["stage1_dev"]:"", - ","); - - if (size (loader_devices) > 1) { - // check if members of a MD are present - map<string,map> tm = Storage::GetTargetMap (); - list<string> md = maplist (map m, tm["/dev/md", "partitions"]:[], { - return m["device"]:""; - }); - if (Mode::test ()) - md = ["/dev/md0"]; - boolean md_found = false; - // try collapse all MD disks - foreach (string md_disk, md, { - list<string> md_members = sort (maplist ( - string s, - integer id, - BootCommon::Md2Partitions (md_disk), - { - return s; - })); - if (Mode::test ()) - md_members = ["/dev/hda1", "/dev/hdb1"]; - - boolean reduce = true; - foreach (string member, md_members, { - if (! contains (loader_devices, member)) - reduce = false; - }); - if (reduce) { - loader_devices = filter (string d, loader_devices, { - return ! contains (md_members, d); - }); - loader_devices = add (loader_devices, md_disk); - } - }); - // check MBRs of all disks holding /boot partition - map<string,integer> boot_md - = BootCommon::Md2Partitions ( - BootCommon::BootPartitionDevice); - if (Mode::test ()) - boot_md = $["/dev/hda1" : 128, "/dev/hdb1" : 129]; - list<string> md_disks = maplist (string d, integer b, boot_md, - { - map p_dev = Storage::GetDiskPartition (d); - return p_dev["disk"]:""; - }); - boolean reduce = true; - foreach (string d, md_disks, { - if (! contains (loader_devices, d)) - reduce = false; - }); - if (reduce) - { - loader_devices = filter (string d, loader_devices, { - return ! contains (md_disks, d); - }); - loader_devices = add (loader_devices, "mbr_md"); - } - if (contains (loader_devices, BootCommon::BootPartitionDevice)) - { - loader_devices = filter (string d, loader_devices, { - return d != BootCommon::BootPartitionDevice; - }); - backup_to_bootsector = true; - if (size (loader_devices) > 0) - { - loader_devices = sort (loader_devices); - BootCommon::loader_device = loader_devices[0]:""; - } - else - { - BootCommon::loader_device = BootCommon::BootPartitionDevice; - } - } - } - else if (size (loader_devices) == 1) - { - BootCommon::loader_device = loader_devices[0]:""; - } -*/ - importMetaData(); return ret; @@ -836,56 +623,6 @@ * @return boolean true if success */ global boolean Save (boolean clean, boolean init, boolean flush) { - // update list of devices -// list<string> loader_devices = [BootCommon::loader_device]; -// if (backup_to_bootsector && contains (BootCommon::getPartitionList(`boot), -// BootCommon::BootPartitionDevice)) -// { -// if (loader_devices[0]:"" != nil && loader_devices[0]:"" != "/dev/null" -// && loader_devices[0]:"" != "") -// { -// loader_devices[1] = BootCommon::BootPartitionDevice; -// } -// else -// { -// loader_devices = [ BootCommon::BootPartitionDevice ]; -// } -// } - - // get the list of device names to install the boot loader stage 1 into: - // - for non-md devices, use just the device name - // - for installation to md arrays: get the list of device names from - // name of md array, either - // - just the container-partitions (according to yast2-storage) or - // ("/dev/md0" -> ["/dev/hda1", ...]) - // - the (cut off) name of the corresponding disk devices - // ("/dev/md0" -> ["/dev/hda1", ...] -> ["/dev/hda", ...]) -// list<list<string> > dev_lists = maplist (string d, loader_devices, { -// if (substring (d, 0, 7) == "/dev/md") -// { -// map<string,integer> md = BootCommon::Md2Partitions (d); -// if (Mode::test ()) -// md = $["/dev/hda1" : 128, "/dev/hdb1" : 129]; -// return maplist (string d, integer b, md, { -// return d; -// }); -// } -// if (d == "mbr_md") -// { -// map<string,integer> md = BootCommon::Md2Partitions -// (BootCommon::BootPartitionDevice); -// if (Mode::test ()) -// md = $["/dev/hda1" : 128, "/dev/hdb1" : 129]; -// return maplist (string d, integer b, md, { -// // get disk device name for this partition or disk device name -// map p_dev = Storage::GetDiskPartition (d); -// return p_dev["disk"]:""; -// }); -// } -// return [d]; -// }); -// loader_devices = flatten (dev_lists); -// BootCommon::globals["stage1_dev"] = mergestring (loader_devices, ","); // now really save the settings boolean ret = BootCommon::Save (clean, init, flush); Modified: trunk/bootloader/src/routines/lilolike.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/bootloader/src/routines/lilolike.... ============================================================================== --- trunk/bootloader/src/routines/lilolike.ycp (original) +++ trunk/bootloader/src/routines/lilolike.ycp Fri Jul 25 16:27:00 2008 @@ -24,6 +24,7 @@ import "Storage"; import "StorageDevices"; import "BootArch"; +import "Map"; global string DiskOrderSummary (); global list<string> DisksOrder (); @@ -1402,8 +1403,12 @@ { integer index = tointeger (bios_id) - tointeger ("0x80"); string grub_dev = sformat ("hd%1", index); - device_mapping[target_dev] = grub_dev; - ids[index] = true; + // FATE #303548 - doesn't add disk with same bios_id with different name (multipath machine) + if (! ids[index]:false) + { + device_mapping[target_dev] = grub_dev; + ids[index] = true; + } } }); // and guess other devices @@ -1491,6 +1496,72 @@ return ret; } +/** + * FATE #303548 - Grub: limit device.map to devices detected by BIOS Int 13 + * The function reduce record (devices) in device.map + * Grub doesn't support more than 8 devices in device.map + * There is selected the first 7 devices + boot or root device + * @param string boot device with udev id name + * @return boolean true if there was deleted any disks from device.map + */ +global boolean ReduceDeviceMapTo8(string boot_dev) +{ + boolean result = false; + + if (size(device_mapping)>8) + { + result = true; + list <string> bios_order = (list <string> ) Map::Values(device_mapping); + //delete all grub devices with order more than 9 + bios_order = filter(string key, bios_order, {return (size(key) < 4);}); + bios_order = lsort(bios_order); + y2debug("ordered values (grub devices): %1", bios_order); + map<string,string> inverse_device_map = $[]; + map<string,string> new_device_map = $[]; + y2milestone("Device map before reducing: %1", device_mapping); + foreach(string key, string value, device_mapping, + { + inverse_device_map[value]=key; + }); + + y2debug("inverse_device_map: %1", inverse_device_map); + integer index = 0; + boolean boot_device_added = false; + foreach(string key, bios_order, + { + string device_name = inverse_device_map[key]:""; + if (index < 7) + { + y2debug("adding device: %1 with key: %2 and index is: %3", device_name, key, index); + new_device_map[device_name]=key; + if (device_name == boot_dev) + boot_device_added = true; + index = index + 1; + } else { + if (boot_device_added) + { + new_device_map[device_name]=key; + break; + } else { + if (haskey(device_mapping, boot_dev)) + { + new_device_map[boot_dev]=device_mapping[boot_dev]:""; + break; + } else { + + y2error("Boot disk device: %1 was not found in device_mapping: %2", boot_dev, device_mapping); + break; + } + } + } + }); + device_mapping = new_device_map; + y2milestone("Device map with the first 7 device + boot device: %1", device_mapping); + } else { + y2milestone("Device map includes less than 9 devices. It is not reduced. device_map: %1", device_mapping); + } + return result; +} } // EOF Modified: trunk/bootloader/src/routines/misc.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/bootloader/src/routines/misc.ycp?... ============================================================================== --- trunk/bootloader/src/routines/misc.ycp (original) +++ trunk/bootloader/src/routines/misc.ycp Fri Jul 25 16:27:00 2008 @@ -1576,8 +1576,31 @@ return true; } } +/** + * Function return boot disk device with udev id name + * @return string name of boot disk like udev id + */ +define string BootDeviceToUdevID() +{ + string device = ""; + if ((BootPartitionDevice != "") || (BootPartitionDevice != nil)) + device = BootPartitionDevice; + if (device == "") + device = RootPartitionDevice; + if (device == "") + return device; + + y2milestone("Boot device is: %1", device); + map p_dev = Storage::GetDiskPartition (device); + + string boot_disk = p_dev["disk"]:""; + + device = DevToLabelUdevID(boot_disk); + y2milestone("Boot disk is %1 and his udev id is: %2", boot_disk, device); + return device; +} } //end of include -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org