ACC SHELL
/**
* File:
* include/bootloader/routines/widgets.ycp
*
* Module:
* Bootloader installation and configuration
*
* Summary:
* Common widgets for being used by several bootloaders
*
* Authors:
* Jiri Srain <jsrain@suse.cz>
* Olaf Dabrunz <od@suse.de>
* Josef Reidinger <jreidinger@suse.cz>
*
* $Id: section_widgets.ycp 59979 2009-12-07 13:27:59Z juhliarik $
*
*/
{
textdomain "bootloader";
import "CWM";
import "Initrd";
import "Label";
import "Mode";
import "Storage";
import "StorageDevices";
import "Bootloader";
import "BootStorage";
import "Popup";
import "FileUtils";
include "bootloader/routines/helps.ycp";
include "bootloader/routines/section_helps.ycp";
boolean validate_image(string widget, map event){
string value = (string) UI::QueryWidget(`id(widget),`Value);
if (value == ""){
Popup::Error(_("Image section must have specified kernel image"));
UI::SetFocus(`id(widget));
return false;
}
if (!Mode::installation() && !Mode::repair()){
if (!FileUtils::Exists(value)){
if (!Popup::YesNo(_("Image file doesn't exist now. Do you really want use it?"))){
UI::SetFocus(`id(widget));
return false;
}
}
}
return true;
}
boolean validate_initrd(string widget, map event){
string value = (string) UI::QueryWidget(`id(widget),`Value);
if (!Mode::installation() && !Mode::repair()){
if (!FileUtils::Exists(value)){
if (!Popup::YesNo(_("Initrd file doesn't exist now. Do you really want use it?"))){
UI::SetFocus(`id(widget));
return false;
}
}
}
return true;
}
map<string,boolean (string, map)> validation_map = $[
"image" : validate_image,
"initrd" : validate_initrd,
];
/**
* Init function for widget value
* @param widget any id of the widget
*/
void SectionOptionInit (string widget) {
UI::ChangeWidget (`id (widget), `Value,
BootCommon::current_section[widget]:"");
}
/**
* Store function of a widget
* @param widget any widget key
* @param event map event description of event that occured
*/
void SectionOptionStore (string widget, map event) {
BootCommon::current_section[widget]
= UI::QueryWidget (`id (widget), `Value);
}
/**
* Map of fallback handlers for events on sections
*/
map<string,any> section_handlers = $[
"init" : SectionOptionInit,
"store" : SectionOptionStore,
];
void InitSectionBool(string widget){
boolean value = BootCommon::current_section[widget]:"false" == "true";
UI::ChangeWidget (`id (widget), `Value, value);
}
void StoreSectionBool(string widget, map event){
boolean value = (boolean)UI::QueryWidget (`id (widget), `Value);
BootCommon::current_section[widget] = value ? "true" : "false";
}
map<string,any> SectionCheckBoxWidget( string name){
return $[
"label" : section_descriptions[name]:name,
"widget" : `checkbox,
"help" : section_help_messages[name]:"",
"init" : InitSectionBool,
"store" : StoreSectionBool
];
}
void InitEnableSelinux (string widget)
{
string append = BootCommon::current_section["append"]:"";
if ((append != "") && (BootCommon::current_section["type"]:"" == "image"))
{
if ((search(append, "security=selinux") !=nil) && (search(append, "selinux=1") != nil)
&& (search(append, "enforcing=0") != nil))
UI::ChangeWidget (`id (widget), `Value, true);
else
UI::ChangeWidget (`id (widget), `Value, false);
} else {
UI::ChangeWidget (`id (widget), `Value, false);
}
if ((BootCommon::current_section["type"]:"" != "image") ||
(BootCommon::current_section["original_name"]:"" == "failsafe"))
UI::ChangeWidget (`id (widget), `Enabled, false);
}
string add_selinux_append (string append)
{
string ret = append;
if ((search(append, "security=selinux") ==nil))
ret = ret + " security=selinux";
if ((search(append, "selinux=1") ==nil))
ret = ret + " selinux=1";
if ((search(append, "enforcing=0") ==nil))
ret = ret + " enforcing=0";
return ret;
}
string delete_selinux_append (string append)
{
string ret = append;
list <string> l_append = splitstring(append, " ");
l_append = filter(string v, l_append,
{
if ((v != "") && (tolower(v)!="security=selinux")
&&(tolower(v)!="selinux=1") && (tolower(v)!="enforcing=0"))
return true;
});
ret = mergestring(l_append, " ");
return ret;
}
void StoreEnableSelinux(string widget, map event)
{
// string append = BootCommon::current_section["append"]:"";
string append = (string)UI::QueryWidget (`id ("append"), `Value);
boolean value = (boolean)UI::QueryWidget (`id (widget), `Value);
if (value)
{
append = add_selinux_append(append);
BootCommon::enable_selinux = true;
} else {
append = delete_selinux_append(append);
BootCommon::enable_selinux = false;
}
BootCommon::current_section["append"] = append;
}
symbol HandleEnableSelinux (string widget, map event)
{
boolean value = (boolean)UI::QueryWidget (`id (widget), `Value);
//string append = BootCommon::current_section["append"]:"";
string append = (string)UI::QueryWidget (`id ("append"), `Value);
if (value)
{
UI::ChangeWidget (`id ("append"), `Value, add_selinux_append(append));
} else {
UI::ChangeWidget (`id ("append"), `Value, delete_selinux_append(append));
}
return nil;
}
map <string,any> EnableSelinux(){
return $[
"label" : _("Enable &SELinux"),
"widget" : `checkbox,
"help" : section_help_messages["enable_selinux"]:"",
"init" : InitEnableSelinux,
"handle": HandleEnableSelinux,
"opt" : [`notify],
"store" : StoreEnableSelinux,
];
}
map<string,any> SectionTextFieldWidget( string name){
map<string,any> ret = $[
"label" : section_descriptions[name]:name,
"widget" : `textentry,
"help" : section_help_messages[name]:"",
];
if (haskey(validation_map,name)){
ret["validate_type"] = `function;
ret["validate_function"] = validation_map[name]:nil;//nil cannot happen
}
return ret;
}
/**
* Handle function of a widget (InputField + browse button)
* @param widget any widget key
* @param event map event description of event that occured
* @return symbol nil
*/
symbol HandleSectionBrowse (string widget, map event) {
string current = (string)UI::QueryWidget (`id (widget), `Value);
if (current == "" || current == nil)
current = "/boot";
// file open popup caption
current = UI::AskForExistingFile (current, "*", _("Select File"));
if (current != nil)
UI::ChangeWidget (`id (widget), `Value, current);
return nil;
}
/**
* Handle function of a widget (InputField + browse button)
* Asks for directory instead file
* @param widget any widget key
* @param event map event description of event that occured
* @return symbol nil
*/
symbol HandleSectionBrowseDirectory (string widget, map event) {
string current = (string)UI::QueryWidget (`id (widget), `Value);
// file open popup caption
current = UI::AskForExistingFile (current, "*", _("Select File"));
if (current != nil)
UI::ChangeWidget (`id (widget), `Value, current);
return nil;
}
/**
* Generic widget of a inputfield + browse button
* Use validation function from validation_map
* if it is necessary create own definition of widget
* @param string lable of widget
* @param string help text for widget
* @param string id of widget
* @return map<string,any> CWS widget
*/
map<string,any> SectionInputFieldBrowseWidget(string id){
string browse = "browse" + id;
map<string,any> ret = $[
"widget" : `custom,
"custom_widget" : `HBox(
`Left(`InputField(`id(id),`opt(`hstretch),
section_descriptions[id]:id)),
`VBox(
`Label(""),
`PushButton(`id(browse),`opt(`notify), Label::BrowseButton())
)
),
"init" : SectionOptionInit,
"store" : SectionOptionStore,
"handle" : HandleSectionBrowse,
"handle_events" : [browse],
"help" : section_help_messages[id]:id,
];
if (haskey(validation_map,id)){
ret["validate_type"] = `function;
ret["validate_function"] = validation_map[id]:nil;//nil cannot happen
}
return ret;
}
map<string,any> SectionInputFieldBrowseDirectoryWidget(string id){
map<string,any> ret = SectionInputFieldBrowseWidget(id);
ret["handle"] = HandleSectionBrowseDirectory;
return ret;
}
void InitSectionInt(string widget){
integer value = tointeger(BootCommon::current_section[widget]:"0");
UI::ChangeWidget (`id (widget), `Value, value);
}
void StoreSectionInt(string widget, map event){
integer value = (integer)UI::QueryWidget (`id (widget), `Value);
BootCommon::current_section[widget] = tostring(value);
}
map<string,any> SectionIntFieldWidget( string name,
integer min, integer max){
map<string,any> ret = $[
"label" : section_descriptions[name]:name,
"widget" : `intfield,
"help" : section_help_messages[name]:name,
"init" : InitSectionInt,
"store" : StoreSectionInt
];
if ( min != nil )
ret["minimum"] = min;
if ( max != nil )
ret["maximum"] = max;
return ret;
}
/**
* Validate function of the name widget
* @param widget any widget key
* @param event map event description of event that occured
* @return boolean true if widget settings ok
*/
boolean SectionNameValidate (string widget, map event) {
string bl = Bootloader::getLoaderType();
list<string> existing = [];
foreach (map<string,any> s, BootCommon::sections, {
existing = add (existing, s["name"]:"");
});
existing = (list<string>)filter (string l, existing, {
return l != BootCommon::current_section_name;
});
existing = (list<string>)add (existing, "");
string new = (string)UI::QueryWidget (`id (widget), `Value);
if (contains (existing, new))
{
usedNameErrorPopup ();
return false;
}
// bnc#456362 filter out special chars like diacritics china chars etc.
if ((Mode::normal()) && (bl == "grub"))
{
string filtered_new =
filterchars (new, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 /\\_.-()");
if (filtered_new != new)
{
Report::Error (_("The name includes unallowable char(s)"));
return false;
}
}
return true;
}
/**
* Store function of the name widget
* @param widget any widget key
* @param event map event description of event that occured
*/
void SectionNameStore (string widget, map event) {
string value = (string)UI::QueryWidget (`id (widget), `Value);
//check if we need change default value in globals
if ( BootCommon::globals["default"]:nil
== BootCommon::current_section[widget]:""){
BootCommon::globals["default"] = value;
}
BootCommon::current_section[widget] = value;
}
/**
* Init function of the root device widget
* @param widget any id of the widget
*/
void RootDeviceInit (string widget) {
y2milestone ("RootDeviceInit: %1", widget);
list<string> available = BootStorage::getPartitionList (`root, Bootloader::getLoaderType());
// if we mount any of these devices by id, label etc., we add a hint to
// that effect to the item
y2milestone ("RootDeviceInit: getHintedPartitionList for %1", available);
available = BootStorage::getHintedPartitionList (available);
UI::ChangeWidget (`id (widget), `Items, available);
UI::ChangeWidget (`id (widget), `Value,
(BootStorage::getHintedPartitionList ([BootCommon::current_section[widget]:""]))[0]:"");
}
/**
* Store function of the root device widget
* @param widget any widget key
* @param event map event description of event that occured
*/
void RootDeviceStore (string widget, map event) {
BootCommon::current_section[widget]
= (splitstring( (string)UI::QueryWidget (`id (widget), `Value), " "))[0]:"";
}
/**
* Handle function of the root device widget
* @param widget any widget key
* @param event map event description of event that occured
* @return symbol to return to wizard sequencer, or nil
*/
symbol RootDeviceHandle (string widget, map event) {
if (event["EventReason"]:nil != "ValueChanged")
return nil;
// append hint string when user changed root device
string current
= (splitstring( (string)UI::QueryWidget (`id (widget), `Value), " "))[0]:"";
// check against the list of existing partitions
list<string> available = BootStorage::getPartitionList (`root, Bootloader::getLoaderType());
if (contains(available, current))
UI::ChangeWidget (`id (widget), `Value,
(BootStorage::getHintedPartitionList ([current]))[0]:"");
return nil;
}
/**
* Init function of widget
* @param widget any id of the widget
*/
void VgaModeInit (string widget) {
list<map> vga_modes = Initrd::VgaModes ();
list items = maplist (map m, vga_modes, {
return `item (`id (sformat ("%1", tohexstring(m["mode"]:0))),
// combo box item
// %1 is X resolution (width) in pixels
// %2 is Y resolution (height) in pixels
// %3 is color depth (usually one of 8, 16, 24, 32)
// %4 is the VGA mode ID (hexadecimal number)
sformat (_("%1x%2, %3 bits (mode %4)"),
m["width"]:0, m["height"]:0, m["color"]:0, tohexstring(m["mode"]:0)));
});
items = prepend(items,`item(`id("ask"), _("Ask for resolution during boot.")));
items = prepend(items,`item(`id("extended"), _("Standard 8-pixel font mode.")));
// item of a combo box
items = prepend (items, `item (`id ("normal"), _("Text Mode")));
UI::ChangeWidget (`id (widget), `Items, items);
SectionOptionInit (widget);
}
/**
* Init function of widget
* @param widget any id of the widget
*/
void ChainloaderInit (string widget) {
list<string> available = BootStorage::getPartitionList (`boot_other, Bootloader::getLoaderType());
UI::ChangeWidget (`id (widget), `Items, available);
SectionOptionInit (widget);
}
/**
* Widget for selecting section type
* @return term widget
*/
term SectionTypesWidget () {
integer count = 0;
term contents = `VBox ();
if (BootCommon::current_section_name != "")
{
contents = add (contents, `Left (`RadioButton (`id ("clone"),
// radio button
_("Clone Selected Section"), true)));
count = count + 1;
}
list<string> section_types = Bootloader::blsection_types();
map<string,string> section_types_descr = $[
// radio button
"image" : _("Image Section"),
// radio button
"xen" : _("Xen Section"),
// radio button (don't translate 'chainloader')
"other" : _("Other System (Chainloader)"),
// radio button
"menu" : _("Menu Section"),
// radio button
"dump" : _("Dump Section"),
];
foreach (string t, section_types, {
if (count > 0)
contents = add (contents, `VSpacing (0.4));
count = count + 1;
contents = add (contents, `Left (`RadioButton (`id (t),
section_types_descr[t]:t, count == 1)));
});
// frame
contents = `Frame (_("Section Type"), `VBox (
`VSpacing (1),
`HBox (
`HSpacing (2),
`RadioButtonGroup (`id (`sect_type), contents),
`HSpacing (2)
),
`VSpacing (1)
));
return contents;
}
/**
* Handle function of a widget
* @param widget string widget key
* @param event map event description of event that occured
* @return symbol to return to wizard sequencer, or nil
*/
symbol SectionTypeHandle (string widget, map event) {
if (event["ID"]:nil != `next)
return nil;
string selected = (string)
UI::QueryWidget (`id (`sect_type), `CurrentButton);
string original_name = selected;
if (original_name == "image")
original_name = "linux";
if (selected != "clone")
{
BootCommon::current_section = $[
"type" : selected,
"original_name" : original_name,
];
}
else
{
BootCommon::current_section["name"] = "";
// fix the problem with missing YaST commnet in menu.lst
// it seems be correct if original_name stay same...
BootCommon::current_section["original_name"] = "";
BootCommon::current_section["__auto"] = false;
// fix for problem with cloning section
if (haskey(BootCommon::current_section,"lines_cache_id"))
BootCommon::current_section = remove(BootCommon::current_section, "lines_cache_id");
}
y2milestone ("Added section template: %1", BootCommon::current_section);
return nil;
}
/**
* Cache for CommonSectionWidgets
*/
map<string,map<string,any> > _common_section_widgets = nil;
/**
* Get common widgets for loader sections
* @return a map describing common loader section related widgets
*/
map<string,map<string,any> > CommonSectionWidgets () {
if (_common_section_widgets == nil)
{
_common_section_widgets = $[
"name" : $[
// text entry
"label" : _("Section &Name"),
"widget" : `textentry,
"validate_type" : `function,
"validate_function" : SectionNameValidate,
"store" : SectionNameStore,
"help" : SectionNameHelp (),
],
"image" : SectionInputFieldBrowseWidget("image"),
"initrd" : SectionInputFieldBrowseWidget("initrd"),
"xen" : SectionInputFieldBrowseWidget("xen"),
"target" : SectionInputFieldBrowseDirectoryWidget("target"),
"parmfile" : SectionInputFieldBrowseWidget("parmfile"),
"dumpto" : $[ //FIXME when exist browse device use it
"label" : section_descriptions["dumpto"]:"dumpto",
"widget" : `textentry,
"help" : section_help_messages["dumpto"]:""
],
"dumptofs" : $[ //FIXME when exist browse device use it
"label" : section_descriptions["dumptofs"]:"dumptofs",
"widget" : `textentry,
"help" : section_help_messages["dumptofs"]:""
],
"root" : $[
"widget" : `combobox,
// combo box
"label" : section_descriptions["root"]:"root",
"opt" : [ `editable, `hstretch, `notify ],
"init" : RootDeviceInit,
"handle" : RootDeviceHandle,
"store" : RootDeviceStore,
"help" : section_help_messages["root"]:"",
],
"vgamode" : $[
"widget" : `combobox,
// combo box
"label" : section_descriptions["vgamode"]:"vgamode",
"opt" : [ `editable, `hstretch ],
"init" : VgaModeInit,
"help" : section_help_messages["vgamode"]:"",
],
"append" : SectionTextFieldWidget("append"),
"xen_append" : SectionTextFieldWidget("xen_append"),
"configfile" : SectionTextFieldWidget("configfile"),
"list" : SectionTextFieldWidget("list"),
"chainloader" : $[
"widget" : `combobox,
"init" : ChainloaderInit,
"help" : section_help_messages["chainloader"]:"",
"label" : section_descriptions["chainloader"]:"chainloader",
"opt" : [ `editable, `hstretch ],
],
"section_type" : $[
"widget" : `func,
"widget_func" : SectionTypesWidget,
"handle" : SectionTypeHandle,
"help" : SectionTypeHelp (),
],
"makeactive" : SectionCheckBoxWidget("makeactive"),
"noverifyroot" : SectionCheckBoxWidget("noverifyroot"),
"remap" : SectionCheckBoxWidget("remap"),
"relocatable" : SectionCheckBoxWidget("relocatable"),
"enable_selinux" : EnableSelinux(),
"prompt" : SectionCheckBoxWidget("prompt"),
"blockoffset" : SectionIntFieldWidget(
"blockoffset",0,nil),
"default" : SectionIntFieldWidget(
"default",1,10),
"timeout" : SectionIntFieldWidget(
"timeout",0,60),
"optional" : SectionCheckBoxWidget("optional"),
"copy" : SectionCheckBoxWidget("copy"),
"other" : //FIXME change to combobox and add proper init function
SectionTextFieldWidget("other"),
];
}
return _common_section_widgets;
}
} // include end
ACC SHELL 2018