[PATCH 4/4] Initial commit of EXTLINUX (with menu) support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This adds EXTLINUX, part of the SYSLINUX family of bootloaders, support to grubby.  This is a merging of the cli and the menu versions of EXTLINUX

This adds:
	--extlinuxmenu - Switch to define that you want to work on EXTLINUX and have it use a pretty menu interface (for the SYSLINUX crowd this is hard coded to vesamenu.c32 as this provides the most flexibility in general and keeps things simple - K.I.S.S.)
	- Adds the neccisary structures to deal with EXTLINUX w/ menus (struct keywordTypes extlinuxmenuKeywords[], and struct configFileInfo extlinuxmenuConfigType)
	- Sadly not a small amount of other code to handle the oddities of EXTLINUX vs. other boot loaders
		- EXTLINUX's menu interface defines the 'default' image based on a completely different symantec than EXTLINUX itself.  In fact both symantecs are needed.  The 'normal' cli based default is defined to load the menuing module, which then re-reads the config and that parses the menu's default.  This 'menu default' is stored within the entry itself, not in a central location.
		- EXTLINUX's menu interface uses the prefix 'menu' to determine that it should parse the option keyword.  I.E.
			menu label string value
			is actually keyword 'menu' and sub-keyword 'label' with the value 'string value'

Note: 'menu label' is allowed spaces, as it isn't parsed by anything other than menu.  'label' is required to not have spaces (thus some of the code in the normal EXTLINUX patch that removes them.)

Note: SYSLINUX in general and by default puts the initrd into the append line and does *not* treat it as a special option.  Adding this support to grubby would be cumbersome at best.  SYSLINUX however has added an initrd keyword that was introduced and deprecated in the same commit.  This keyword is intended only for things like grubby which do not understand this syntax.  This does mean that grubby will not understand, correctly, initrd's added to the append line if a user hand-edit's their extlinux.conf file.

Signed-off-by: John 'Warthog9' Hawley <warthog9@xxxxxxxxxxxxxx>
---
 grubby/grubby.c |  171 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 164 insertions(+), 7 deletions(-)

diff --git a/grubby/grubby.c b/grubby/grubby.c
index 9f130e4..c6ee88a 100644
--- a/grubby/grubby.c
+++ b/grubby/grubby.c
@@ -247,7 +247,20 @@ struct keywordTypes extlinuxKeywords[] = {
     { "prompt",     LT_UNKNOWN,     ' ' },
     { NULL,	    0, 0 },
 };
+struct keywordTypes extlinuxmenuKeywords[] = {
+    { "label",      LT_TITLE,	    ' ' },
+    { "menu label", LT_GENERIC,     ' ' },
+    { "root",	    LT_ROOT,	    ' ' },
+    { "default",    LT_DEFAULT,	    ' ' },
+    { "kernel",     LT_KERNEL,      ' ' },
+    { "initrd",	    LT_INITRD,      ' ' },
+    { "append",	    LT_KERNELARGS,  ' ' },
+    { "menu",       LT_OTHER,       ' ' },
+    { NULL,	    0, 0 },
+};
 int useextlinuxmenu;
+char * extlinuxmenudefault;
+
 struct configFileInfo eliloConfigType = {
     "/boot/efi/EFI/redhat/elilo.conf",	    /* defaultConfig */
     eliloKeywords,			    /* keywords */
@@ -338,6 +351,21 @@ struct configFileInfo extlinuxConfigType = {
     0,                                      /* mbConcatArgs */
 };
 
+struct configFileInfo extlinuxmenuConfigType = {
+    "/boot/extlinux/extlinux.conf",         /* defaultConfig */
+    extlinuxmenuKeywords,                   /* keywords */
+    0,                                      /* defaultIsIndex */
+    0,                                      /* defaultSupportSaved */
+    LT_TITLE,                               /* entrySeparator */
+    1,                                      /* needsBootPrefix */
+    0,                                      /* argsInQuotes */
+    255,                                    /* maxTitleLength */
+    0,                                      /* titleBracketed */
+    0,                                      /* mbHyperFirst */
+    0,                                      /* mbInitRdIsModule */
+    0,                                      /* mbConcatArgs */
+};
+
 struct grubConfig {
     struct singleLine * theLines;
     struct singleEntry * entries;
@@ -462,8 +490,13 @@ static int isBracketedTitle(struct singleLine * line) {
 
 static int isEntrySeparator(struct singleLine * line,
                             struct configFileInfo * cfi) {
-    return line->type == cfi->entrySeparator || line->type == LT_OTHER ||
-	(cfi->titleBracketed && isBracketedTitle(line));
+    if( useextlinuxmenu != 0 ){
+	    return line->type == cfi->entrySeparator ||
+		(cfi->titleBracketed && isBracketedTitle(line));
+    } else {
+	    return line->type == cfi->entrySeparator || line->type == LT_OTHER ||
+		(cfi->titleBracketed && isBracketedTitle(line));
+    }
 }
 
 /* extract the title from within brackets (for zipl) */
@@ -747,6 +780,14 @@ static struct grubConfig * readConfig(const char * inName,
 	    entry->next = NULL;
 	}
 
+	/* Work around for the fact that extlinux stores the menu default in the entry itself */
+	if ( useextlinuxmenu == 2 && line->type == LT_OTHER ){	// We are using extlinux and we have a 'menu' entry
+		if ( line->numElements > 0 && strcmp(line->elements[1].item, "default") == 0 ){
+			cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
+			defaultLine = line;
+		}
+	} // End work arounds for extlinuxmenu
+
 	if (line->type == LT_DEFAULT && line->numElements == 2) {
 	    cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
 	    defaultLine = line;
@@ -888,9 +929,21 @@ static struct grubConfig * readConfig(const char * inName,
 		    if (line->type == LT_TITLE) break;
 
                 if (!cfi->titleBracketed) {
-                    if (line && (line->numElements >= 2) && 
-                        !strcmp(defaultLine->elements[1].item,
-                                line->elements[1].item)) break;
+		    if ( useextlinuxmenu == 2 ){
+			for (line = entry->lines; line; line = line->next){
+				if (line->type == LT_OTHER && strcmp(line->elements[1].item, "default") == 0 ){
+					break;
+				}
+			}
+			
+			if( line && (line->numElements >= 2) && strcmp(line->elements[1].item, "default") == 0 ){
+				break;
+			}
+		    } else {
+			    if (line && (line->numElements >= 2) && 
+				!strcmp(defaultLine->elements[1].item,
+					line->elements[1].item)) break;
+		    }
                 } else if (line) {
                     if (!strcmp(defaultLine->elements[1].item, 
                                 extractTitle(line))) break;
@@ -912,6 +965,53 @@ static struct grubConfig * readConfig(const char * inName,
     return cfg;
 }
 
+static char * getDefault(struct grubConfig * cfg){
+    struct singleEntry * entry;
+    struct singleLine * line;
+    char * returnvalue;
+    int i;
+
+    if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT) return NULL;
+    if (cfg->defaultImage == DEFAULT_SAVED) return NULL;
+
+    if (cfg->defaultImage > -1) {
+	if (cfg->cfi->defaultIsIndex) {
+	    returnvalue = malloc(30);
+	    sprintf(returnvalue,"%d",cfg->defaultImage);
+	    return returnvalue;
+	} else {
+	    int image = cfg->defaultImage;
+
+	    entry = cfg->entries;
+	    while (entry && entry->skip) entry = entry->next;
+
+	    i = 0;
+	    while (entry && i < image) {
+		entry = entry->next;
+
+		while (entry && entry->skip) entry = entry->next;
+		i++;
+	    }
+
+	    if (!entry){
+		 return NULL;
+	    }
+
+	    line = getLineByType(LT_TITLE, entry->lines);
+
+	    if (line && line->numElements >= 2){
+		returnvalue = strdup(line->elements[1].item);
+		return returnvalue;
+            }else if (line && (line->numElements == 1) && 
+                     cfg->cfi->titleBracketed) {
+		returnvalue = strdup(extractTitle(line));
+		return returnvalue;
+            }
+	}
+    }
+    return NULL;
+}
+
 static void writeDefault(FILE * out, char * indent, 
 			 char * separator, struct grubConfig * cfg) {
     struct singleEntry * entry;
@@ -944,7 +1044,10 @@ static void writeDefault(FILE * out, char * indent,
 
 	    line = getLineByType(LT_TITLE, entry->lines);
 
-	    if (line && line->numElements >= 2)
+	    if( useextlinuxmenu == 2 )
+		fprintf(out, "%sdefault%s%s\n", indent, separator, 
+			"vesamenu.c32");
+	    else if (line && line->numElements >= 2)
 		fprintf(out, "%sdefault%s%s\n", indent, separator, 
 			line->elements[1].item);
             else if (line && (line->numElements == 1) && 
@@ -1048,6 +1151,12 @@ static int writeConfig(struct grubConfig * cfg, char * outName,
 
 	line = entry->lines;
 	while (line) {
+	    if( line->type == LT_OTHER && useextlinuxmenu != 0 ){
+		    if( line->numElements > 1 && strcmp( line->elements[1].item, "default" ) == 0 ){
+			    line = line->next;
+			    continue;
+		     }
+	    }
 	    if (lineWrite(out, line, cfg->cfi) == -1) {
                 fprintf(stderr, _("grubby: error writing %s: %s\n"),
                         tmpOutName, strerror(errno));
@@ -1055,6 +1164,35 @@ static int writeConfig(struct grubConfig * cfg, char * outName,
                 unlink(tmpOutName);
                 return 1;
             }
+	    if ( line->type == LT_TITLE && useextlinuxmenu != 0 ){
+		char * defaultKernel;
+		struct singleLine * tempLine;
+		struct singleEntry * new;
+
+	        new = malloc(sizeof(*new));
+	        new->skip = 0;
+	        new->multiboot = 0;
+	        new->next = cfg->entries;
+	        new->lines = NULL;
+
+		defaultKernel = getDefault(cfg);
+
+		if( defaultKernel == NULL ) defaultKernel = "";
+			
+		//if( line->elements[1].item != NULL && strcmp(defaultKernel, line->elements[1].item) == 0 ){
+		if( ( cfg->defaultImage == i ) || ( line->elements[1].item != NULL && strcmp(defaultKernel, line->elements[1].item) == 0 ) ){
+			tempLine = addLine(new, cfg->cfi, LT_OTHER,
+							cfg->primaryIndent, "default");
+		        if (lineWrite(out, tempLine, cfg->cfi) == -1) {
+			    fprintf(stderr, _("grubby: error writing %s: %s\n"),
+			    		tmpOutName, strerror(errno));
+			    fclose(out);
+			    unlink(tmpOutName);
+			    return 1;
+		        }
+		}
+		if( defaultKernel != NULL && strcmp(defaultKernel,"") != 0 ) free(defaultKernel);
+            }
 	    line = line->next;
 	}
     }
@@ -2501,6 +2639,10 @@ int addNewKernel(struct grubConfig * config, struct singleEntry * template,
 			}
 			newLine = addLine(new, config->cfi, LT_TITLE,
 					  config->primaryIndent, templabel);
+			if( useextlinuxmenu == 2 ){	// 2 means that we are in the actual menu portion
+				newLine = addLine(new, config->cfi, LT_GENERIC,
+						  config->primaryIndent, newKernelTitle);
+			}
 			free(templabel);
 		}else{
 			newLine = addLine(new, config->cfi, LT_TITLE,
@@ -2591,6 +2733,7 @@ int main(int argc, const char ** argv) {
     int configureLilo = 0, configureELilo = 0, configureGrub = 0;
     int configureYaboot = 0, configureSilo = 0, configureZipl = 0;
     int configureExtLinux = 0;
+    int configureExtLinuxMenu = 0;
     int bootloaderProbe = 0;
     char * updateKernelPath = NULL;
     char * newKernelPath = NULL;
@@ -2649,6 +2792,8 @@ int main(int argc, const char ** argv) {
 	    _("configure elilo bootloader") },
 	{ "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
 	    _("configure extlinux bootloader (from syslinux)") },
+	{ "extlinuxmenu", 0, POPT_ARG_NONE, &configureExtLinuxMenu, 0,
+	    _("configure extlinux bootloader w/ menu support (from syslinux)") },
 	{ "grub", 0, POPT_ARG_NONE, &configureGrub, 0,
 	    _("configure grub bootloader") },
 	{ "info", 0, POPT_ARG_STRING, &kernelInfo, 0,
@@ -2693,6 +2838,7 @@ int main(int argc, const char ** argv) {
     };
 
     useextlinuxmenu=0;
+    extlinuxmenudefault=NULL;
 
     signal(SIGSEGV, traceback);
     _nash_context = nashNewContext();
@@ -2723,7 +2869,7 @@ int main(int argc, const char ** argv) {
 
     if ((configureLilo + configureGrub + configureELilo + 
 		configureYaboot + configureSilo + configureZipl +
-		configureExtLinux ) > 1) {
+		configureExtLinux + configureExtLinuxMenu ) > 1) {
 	fprintf(stderr, _("grubby: cannot specify multiple bootloaders\n"));
 	return 1;
     } else if (bootloaderProbe && grubConfig) {
@@ -2745,6 +2891,9 @@ int main(int argc, const char ** argv) {
     } else if (configureExtLinux) {
 	cfi = &extlinuxConfigType;
 	useextlinuxmenu=1;
+    } else if (configureExtLinuxMenu) {
+	cfi = &extlinuxmenuConfigType;
+	useextlinuxmenu=2;
     }
 
     if (!cfi) {
@@ -2867,6 +3016,14 @@ int main(int argc, const char ** argv) {
 		erc = checkForExtLinux(lconfig);
 	} 
 
+	if (!access(extlinuxmenuConfigType.defaultConfig, F_OK)) {
+	    lconfig = readConfig(extlinuxmenuConfigType.defaultConfig, &extlinuxmenuConfigType);
+	    if (!lconfig)
+		erc = 1;
+	    else
+		erc = checkForExtLinux(lconfig);
+	} 
+	
 	if (lrc == 1 || grc == 1) return 1;
 
 	if (lrc == 2) printf("lilo\n");
_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux