[Fedora-xen] [patch 3/4] elilo multiboot support (grubby: args)

Aron Griffis aron at hp.com
Wed Jun 7 21:38:21 UTC 2006


elilo handles hypervisor args by putting a "--" separator on the
append line, like this:

    append="hyper args -- kernel args"

This patch modifies updateActualImage() to handle this situation,
including removing the hypervisor args plus separator when a multiboot
template is used to construct a non-multiboot entry.

Signed-off-by: Aron Griffis <aron at hp.com>

 grubby.c |  279 ++++++++++++++++++++++++++++-----------------------------------
 1 file changed, 128 insertions(+), 151 deletions(-)

--- grubby.c.2	2006-06-07 16:14:33.000000000 -0400
+++ grubby.c	2006-06-07 16:16:44.000000000 -0400
@@ -101,6 +101,7 @@
     int titleBracketed;
     int mbHyperFirst;
     int mbInitRdIsModule;
+    int mbConcatArgs;
 };
 
 struct keywordTypes grubKeywords[] = {
@@ -127,6 +128,7 @@
     0,                                      /* titleBracketed */
     1,                                      /* mbHyperFirst */
     1,                                      /* mbInitRdIsModule */
+    0,                                      /* mbConcatArgs */
 };
 
 struct keywordTypes yabootKeywords[] = {
@@ -224,6 +226,7 @@
     0,                                      /* titleBracketed */
     0,                                      /* mbHyperFirst */
     0,                                      /* mbInitRdIsModule */
+    1,                                      /* mbConcatArgs */
 };
 
 struct configFileInfo liloConfigType = {
@@ -238,6 +241,7 @@
     0,                                      /* titleBracketed */
     0,                                      /* mbHyperFirst */
     0,                                      /* mbInitRdIsModule */
+    0,                                      /* mbConcatArgs */
 };
 
 struct configFileInfo yabootConfigType = {
@@ -252,6 +256,7 @@
     0,                                      /* titleBracketed */
     0,                                      /* mbHyperFirst */
     0,                                      /* mbInitRdIsModule */
+    0,                                      /* mbConcatArgs */
 };
 
 struct configFileInfo siloConfigType = {
@@ -266,6 +271,7 @@
     0,                                      /* titleBracketed */
     0,                                      /* mbHyperFirst */
     0,                                      /* mbInitRdIsModule */
+    0,                                      /* mbConcatArgs */
 };
 
 struct configFileInfo ziplConfigType = {
@@ -280,6 +286,7 @@
     1,                                      /* titleBracketed */
     0,                                      /* mbHyperFirst */
     0,                                      /* mbInitRdIsModule */
+    0,                                      /* mbConcatArgs */
 };
 
 struct grubConfig {
@@ -1754,14 +1761,13 @@
     struct singleEntry * entry;
     struct singleLine * line, * rootLine;
     int index = 0;
-    int i, j, k;
+    int i, k;
     const char ** newArgs, ** oldArgs;
     const char ** arg;
-    const char * chptr;
-    int useKernelArgs = 0;
-    int useRoot = 0;
+    int useKernelArgs, useRoot;
     int firstElement;
     int *usedElements, *usedArgs;
+    int doreplace;
 
     if (!image) return 0;
 
@@ -1788,54 +1794,102 @@
 	}
     }
 
-    for (i = 0; cfg->cfi->keywords[i].key; i++)
-	if (cfg->cfi->keywords[i].type == LT_KERNELARGS) break;
 
-    if (cfg->cfi->keywords[i].key)
-	useKernelArgs = 1;
+    useKernelArgs = (getKeywordByType(LT_KERNELARGS, cfg->cfi)
+		     && (!multibootArgs || cfg->cfi->mbConcatArgs));
 
-    for (i = 0; cfg->cfi->keywords[i].key; i++)
-	if (cfg->cfi->keywords[i].type == LT_ROOT) break;
+    useRoot = (getKeywordByType(LT_ROOT, cfg->cfi)
+	       && !multibootArgs);
 
-    if (cfg->cfi->keywords[i].key)
-	useRoot = 1;
+    for (k = 0, arg = newArgs; *arg; arg++, k++) ;
+    usedArgs = calloc(k, sizeof(*usedArgs));
 
-    k = 0;
-    for (arg = newArgs; *arg; arg++)
-        k++;
-    usedArgs = calloc(k, sizeof(int));
+    for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
 
-    while ((entry = findEntryByPath(cfg, image, prefix, &index))) {
-	index++;
+	if (multibootArgs && !entry->multiboot)
+	    continue;
 
-	line = entry->lines;
-	while (line && line->type != LT_KERNEL) line = line->next;
-	if (!line) continue;
-	firstElement = 2;
-
-        if (entry->multiboot && !multibootArgs) {
-            /* first mb module line is the real kernel */
-            while (line && line->type != LT_MBMODULE) line = line->next;
-            firstElement = 2;
-        } else if (useKernelArgs) {
-	    while (line && line->type != LT_KERNELARGS) line = line->next;
+	/* Determine where to put the args.  If this config supports
+	 * LT_KERNELARGS, use that.  Otherwise use
+	 * LT_HYPER/LT_KERNEL/LT_MBMODULE lines.
+	 */
+	if (useKernelArgs) {
+	    line = getLineByType(LT_KERNELARGS, entry->lines);
+	    if (!line) {
+		/* no LT_KERNELARGS, need to add it */
+		line = addLine(entry, cfg->cfi, LT_KERNELARGS, 
+			       cfg->secondaryIndent, NULL);
+	    }
 	    firstElement = 1;
+
+	} else if (multibootArgs) {
+	    line = getLineByType(LT_HYPER, entry->lines);
+	    if (!line) {
+		/* a multiboot entry without LT_HYPER? */
+		continue;
+	    }
+	    firstElement = 2;
+
+	} else {
+	    line = getLineByType2(LT_KERNEL, LT_MBMODULE, entry->lines);
+	    if (!line) {
+		/* no LT_KERNEL or LT_MBMODULE in this entry? */
+		continue;
+	    }
+	    firstElement = 2;
 	}
 
-	if (!line && useKernelArgs) {
-	    /* no append in there, need to add it */
-	    line = addLine(entry, cfg->cfi, LT_KERNELARGS, NULL, NULL);
+	/* handle the elilo case which does:
+	 *   append="hypervisor args -- kernel args"
+	 */
+	if (entry->multiboot && cfg->cfi->mbConcatArgs) {
+	    /* this is a multiboot entry, make sure there's
+	     * -- on the args line
+	     */
+	    for (i = firstElement; i < line->numElements; i++) {
+		if (!strcmp(line->elements[i].item, "--"))
+		    break;
+	    }
+	    if (i == line->numElements) {
+		/* assume all existing args are kernel args,
+		 * prepend -- to make it official
+		 */
+		insertElement(line, "--", firstElement);
+		i = firstElement;
+	    }
+	    if (!multibootArgs) {
+		/* kernel args start after the -- */
+		firstElement = i + 1;
+	    }
+	} else if (cfg->cfi->mbConcatArgs) {
+	    /* this is a non-multiboot entry, remove hyper args */
+	    for (i = firstElement; i < line->numElements; i++) {
+		if (!strcmp(line->elements[i].item, "--"))
+		    break;
+	    }
+	    if (i < line->numElements) {
+		/* remove args up to -- */
+		while (strcmp(line->elements[firstElement].item, "--"))
+		    removeElement(line, firstElement);
+		/* remove -- */
+		removeElement(line, firstElement);
+	    }
 	}
 
-        usedElements = calloc(line->numElements, sizeof(int));
-
-        k = 0;
-	for (arg = newArgs; *arg; arg++) {
-            if (usedArgs[k]) {
-                k++;
-                continue;
-            }
+        usedElements = calloc(line->numElements, sizeof(*usedElements));
+
+	for (k = 0, arg = newArgs; *arg; arg++, k++) {
+            if (usedArgs[k]) continue;
+
+	    doreplace = 1;
 	    for (i = firstElement; i < line->numElements; i++) {
+		if (multibootArgs && cfg->cfi->mbConcatArgs && 
+		    !strcmp(line->elements[i].item, "--")) 
+		{
+		    /* reached the end of hyper args, insert here */
+		    doreplace = 0;
+		    break;  
+		}
                 if (usedElements[i])
                     continue;
 		if (!argMatch(line->elements[i].item, *arg)) {
@@ -1844,91 +1898,62 @@
 		    break;
                 }
             }
-	    chptr = strchr(*arg, '=');
 
-	    if (i < line->numElements) {
-		/* replace */
+	    if (i < line->numElements && doreplace) {
+		/* direct replacement */
 		free(line->elements[i].item);
 		line->elements[i].item = strdup(*arg);
-	    } else if (useRoot && !strncmp(*arg, "root=/dev/", 10) && *chptr) {
-		rootLine = entry->lines;
-		while (rootLine && rootLine->type != LT_ROOT) 
-		    rootLine = rootLine->next;
-		if (!rootLine) {
-		    rootLine = addLine(entry, cfg->cfi, LT_ROOT, NULL, NULL);
-		    rootLine->elements = realloc(rootLine->elements,
-			    2 * sizeof(*rootLine->elements));
-		    rootLine->numElements++;
-		    rootLine->elements[1].indent = strdup("");
-		    rootLine->elements[1].item = strdup("");
-		}
 
-		free(rootLine->elements[1].item);
-		rootLine->elements[1].item = strdup(chptr + 1);
-	    } else {
-		/* append */
-		line->elements = realloc(line->elements,
-			(line->numElements + 1) * sizeof(*line->elements));
-		line->elements[line->numElements].item = strdup(*arg);
-		usedElements = realloc(usedElements,
-			(line->numElements + 1) * sizeof(int));
-		usedElements[line->numElements] = 1;
-
-		if (line->numElements > 1) {
-		    /* add to existing list of arguments */
-		    line->elements[line->numElements].indent = 
-			line->elements[line->numElements - 1].indent;
-		    line->elements[line->numElements - 1].indent = strdup(" ");
+	    } else if (useRoot && !strncmp(*arg, "root=/dev/", 10)) {
+		/* root= replacement */
+		rootLine = getLineByType(LT_ROOT, entry->lines);
+		if (rootLine) {
+		    free(rootLine->elements[1].item);
+		    rootLine->elements[1].item = strdup(*arg + 5);
 		} else {
-		    /* First thing on this line; treat a bit differently. Note
-		       this is only possible if we've added a LT_KERNELARGS
-		       entry */
-		    line->elements[line->numElements].indent = strdup("");
+		    rootLine = addLine(entry, cfg->cfi, LT_ROOT, 
+				       cfg->secondaryIndent, *arg + 5);
 		}
+	    }
 
-		line->numElements++;
+	    else {
+		/* insert/append */
+		insertElement(line, *arg, i);
+		usedElements = realloc(usedElements, line->numElements *
+				       sizeof(*usedElements));
+		memmove(&usedElements[i + 1], &usedElements[i],
+			line->numElements - i - 1);
+		usedElements[i] = 1;
 
 		/* if we updated a root= here even though there is a
 		   LT_ROOT available we need to remove the LT_ROOT entry
 		   (this will happen if we switch from a device to a label) */
 		if (useRoot && !strncmp(*arg, "root=", 5)) {
-		    rootLine = entry->lines;
-		    while (rootLine && rootLine->type != LT_ROOT)
-			rootLine = rootLine->next;
-		    if (rootLine) {
+		    rootLine = getLineByType(LT_ROOT, entry->lines);
+		    if (rootLine)
 			removeLine(entry, rootLine);
-		    }
 		}
 	    }
-            k++;
 	}
 
         free(usedElements);
 
-	/* no arguments to remove (i.e. no append line) */
-	if (!line) continue;
-
-	/* this won't remove an LT_ROOT item properly (but then again,
-	   who cares? */
 	for (arg = oldArgs; *arg; arg++) {
-	    for (i = firstElement; i < line->numElements; i++)
-		if (!argMatch(line->elements[i].item, *arg))
+	    for (i = firstElement; i < line->numElements; i++) {
+		if (multibootArgs && cfg->cfi->mbConcatArgs && 
+		    !strcmp(line->elements[i].item, "--")) 
+		    /* reached the end of hyper args, stop here */
+		    break;
+		if (!argMatch(line->elements[i].item, *arg)) {
+		    removeElement(line, i);
 		    break;
-
-	    if (i < line->numElements) {
-		/* if this isn't the first argument the previous argument
-		   gets this arguments post-indention */
-		if (i > firstElement) {
-		    free(line->elements[i - 1].indent);
-		    line->elements[i - 1].indent = line->elements[i].indent;
 		}
-		
-		free(line->elements[i].item);
-
-		for (j = i + 1; j < line->numElements; j++)
-		    line->elements[j - 1] = line->elements[j];
-
-		line->numElements--;
+	    }
+	    /* handle removing LT_ROOT line too */
+	    if (useRoot && !strncmp(*arg, "root=", 5)) {
+		rootLine = getLineByType(LT_ROOT, entry->lines);
+		if (rootLine)
+		    removeLine(entry, rootLine);
 	    }
 	}
 
@@ -2318,54 +2343,6 @@
 		    needs &= ~NEED_INITRD;
 		}
 
-				strdup(tmplLine->elements[i].indent);
-	    }
-
-            lastLine = tmplLine;
-	    if (tmplLine->type == LT_KERNEL && tmplLine->numElements >= 2) {
-                char * repl;
-                if (!template->multiboot) {
-                    needs &= ~KERNEL_KERNEL;
-                    repl = newKernelPath;
-                } else { 
-                    needs &= ~KERNEL_MB;
-                    repl = newMBKernel;
-                }
-                if (new->multiboot && !template->multiboot) {
-                    free(newLine->elements[0].item);
-                    newLine->elements[0].item = strdup("module");
-                    newLine->type = LT_MBMODULE;
-                }
-		free(newLine->elements[1].item);
-                rootspec = getRootSpecifier(tmplLine->elements[1].item);
-                if (rootspec != NULL) {
-                    newLine->elements[1].item = sdupprintf("%s%s",
-                                                           rootspec,
-                                                           repl + 
-                                                           strlen(prefix));
-                } else {
-                    newLine->elements[1].item = strdup(repl + 
-                                                       strlen(prefix));
-                }
-            } else if (tmplLine->type == LT_MBMODULE && 
-                       tmplLine->numElements >= 2 && (needs & KERNEL_KERNEL)) {
-                needs &= ~KERNEL_KERNEL;
-                if (!new->multiboot && template->multiboot) {
-                    free(newLine->elements[0].item);
-                    newLine->elements[0].item = strdup("kernel");
-                    newLine->type = LT_KERNEL;
-                }
-		free(newLine->elements[1].item);
-                rootspec = getRootSpecifier(tmplLine->elements[1].item);
-                if (rootspec != NULL) {
-                    newLine->elements[1].item = sdupprintf("%s%s",
-                                                           rootspec,
-                                                           newKernelPath + 
-                                                           strlen(prefix));
-                } else {
-                    newLine->elements[1].item = strdup(newKernelPath + 
-                                                       strlen(prefix));
-                }
 	    } else if (tmplLine->type == LT_INITRD && 
 		       tmplLine->numElements >= 2 && 
 		       (needs & NEED_INITRD)) {




More information about the Fedora-xen mailing list