# HG changeset patch
# User agriffis(a)cheo.zko.hp.com
# Node ID bbebf7a97ae1e13bb2b3bce3dcc999a7de53aa98
# Parent 85b711b5111c64599507a5526427476d1163d6bf
Modify updateActualImage to handle elilo-style args
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.
Grubby builds with this patch, and the test suite doesn't report any
new regressions.
Signed-off-by: Aron Griffis <aron(a)hp.com>
grubby.c | 258 ++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 142 insertions(+), 116 deletions(-)
diff -r 85b711b5111c -r bbebf7a97ae1 grubby/grubby.c
--- a/grubby/grubby.c Thu Jun 29 16:46:55 2006 -0400
+++ b/grubby/grubby.c Thu Jun 29 16:56:35 2006 -0400
@@ -115,6 +115,7 @@ struct configFileInfo {
int titleBracketed;
int mbHyperFirst;
int mbInitRdIsModule;
+ int mbConcatArgs;
};
struct keywordTypes grubKeywords[] = {
@@ -141,6 +142,7 @@ struct configFileInfo grubConfigType = {
0, /* titleBracketed */
1, /* mbHyperFirst */
1, /* mbInitRdIsModule */
+ 0, /* mbConcatArgs */
};
struct keywordTypes yabootKeywords[] = {
@@ -238,6 +240,7 @@ struct configFileInfo eliloConfigType =
0, /* titleBracketed */
0, /* mbHyperFirst */
0, /* mbInitRdIsModule */
+ 1, /* mbConcatArgs */
};
struct configFileInfo liloConfigType = {
@@ -252,6 +255,7 @@ struct configFileInfo liloConfigType = {
0, /* titleBracketed */
0, /* mbHyperFirst */
0, /* mbInitRdIsModule */
+ 0, /* mbConcatArgs */
};
struct configFileInfo yabootConfigType = {
@@ -266,6 +270,7 @@ struct configFileInfo yabootConfigType =
0, /* titleBracketed */
0, /* mbHyperFirst */
0, /* mbInitRdIsModule */
+ 0, /* mbConcatArgs */
};
struct configFileInfo siloConfigType = {
@@ -280,6 +285,7 @@ struct configFileInfo siloConfigType = {
0, /* titleBracketed */
0, /* mbHyperFirst */
0, /* mbInitRdIsModule */
+ 0, /* mbConcatArgs */
};
struct configFileInfo ziplConfigType = {
@@ -294,6 +300,7 @@ struct configFileInfo ziplConfigType = {
1, /* titleBracketed */
0, /* mbHyperFirst */
0, /* mbInitRdIsModule */
+ 0, /* mbConcatArgs */
};
struct grubConfig {
@@ -1742,14 +1749,13 @@ int updateActualImage(struct grubConfig
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;
@@ -1776,53 +1782,102 @@ int updateActualImage(struct grubConfig
}
}
- 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;
-
- for (i = 0; cfg->cfi->keywords[i].key; i++)
- if (cfg->cfi->keywords[i].type == LT_ROOT) break;
-
- if (cfg->cfi->keywords[i].key)
- useRoot = 1;
-
- k = 0;
- for (arg = newArgs; *arg; arg++)
- k++;
- usedArgs = calloc(k, sizeof(int));
-
- while ((entry = findEntryByPath(cfg, image, prefix, &index))) {
- index++;
-
- line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);
- 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;
+
+ useKernelArgs = (getKeywordByType(LT_KERNELARGS, cfg->cfi)
+ && (!multibootArgs || cfg->cfi->mbConcatArgs));
+
+ useRoot = (getKeywordByType(LT_ROOT, cfg->cfi)
+ && !multibootArgs);
+
+ for (k = 0, arg = newArgs; *arg; arg++, k++) ;
+ usedArgs = calloc(k, sizeof(*usedArgs));
+
+ for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
+
+ if (multibootArgs && !entry->multiboot)
+ continue;
+
+ /* 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;
- }
-
- if (!line && useKernelArgs) {
- /* no append in there, need to add it */
- line = addLine(entry, cfg->cfi, LT_KERNELARGS, NULL, NULL);
- }
-
- usedElements = calloc(line->numElements, sizeof(int));
-
- k = 0;
- for (arg = newArgs; *arg; arg++) {
- if (usedArgs[k]) {
- k++;
- continue;
- }
+
+ } else if (multibootArgs) {
+ line = getLineByType(LT_HYPER, entry->lines);
+ if (!line) {
+ /* a multiboot entry without LT_HYPER? */
+ continue;
+ }
+ firstElement = 2;
+
+ } else {
+ line = getLineByType(LT_KERNEL|LT_MBMODULE, entry->lines);
+ if (!line) {
+ /* no LT_KERNEL or LT_MBMODULE in this entry? */
+ continue;
+ }
+ firstElement = 2;
+ }
+
+ /* 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(*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)) {
@@ -1831,91 +1886,62 @@ int updateActualImage(struct grubConfig
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("");
+
+ } 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 {
+ rootLine = addLine(entry, cfg->cfi, LT_ROOT,
+ cfg->secondaryIndent, *arg + 5);
}
-
- 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 {
- /* 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("");
- }
-
- 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 (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;
+ if (!argMatch(line->elements[i].item, *arg)) {
+ removeElement(line, i);
+ break;
}
-
- 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);
}
}