You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
6.4 KiB
198 lines
6.4 KiB
2 years ago
|
From ff38bf8209faf54c25e15b1fcec4184fee1f39e9 Mon Sep 17 00:00:00 2001
|
||
|
From: Robert Marshall <rmarshall@redhat.com>
|
||
|
Date: Tue, 13 Dec 2016 18:20:15 -0500
|
||
|
Subject: [PATCH 34/55] Don't assume --make-default just because --set-index
|
||
|
was passed.
|
||
|
|
||
|
grubby previously made the assumption that every time a new
|
||
|
boot entry gets added using --set-index, it should be the default. Due
|
||
|
to this behavior, it also masked an logic error that prevented the
|
||
|
selection of the proper index in cases where it was necessary to
|
||
|
dynamically pick a new default boot entry, or to keep the existing
|
||
|
default boot entry when its position in the config file moved.
|
||
|
|
||
|
Resolves: rhbz#1285601
|
||
|
---
|
||
|
grubby.c | 138 ++++++++++++++++++++++++++++++++++++++-----------------
|
||
|
1 file changed, 97 insertions(+), 41 deletions(-)
|
||
|
|
||
|
diff --git a/grubby.c b/grubby.c
|
||
|
index 1f712ec1391..fcca6364887 100644
|
||
|
--- a/grubby.c
|
||
|
+++ b/grubby.c
|
||
|
@@ -2498,66 +2498,121 @@ void markRemovedImage(struct grubConfig *cfg, const char *image,
|
||
|
entry->skip = 1;
|
||
|
}
|
||
|
|
||
|
-void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
|
||
|
+void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
|
||
|
const char *defaultKernelPath, int newBootEntryIsDefault,
|
||
|
- const char *prefix, int flags, int newDefaultBootEntryIndex)
|
||
|
+ const char *prefix, int flags,
|
||
|
+ int newDefaultBootEntryIndex, int newBootEntryIndex)
|
||
|
{
|
||
|
- struct singleEntry *entry, *entry2, *newDefault;
|
||
|
- int i, j;
|
||
|
+ struct singleEntry *bootEntry, *newDefault;
|
||
|
+ int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
|
||
|
|
||
|
+ /* handle the two cases where the user explictly picks the default
|
||
|
+ * boot entry index as it would exist post-modification */
|
||
|
+
|
||
|
+ /* Case 1: user chose to make the latest boot entry the default */
|
||
|
if (newBootEntryIsDefault) {
|
||
|
- config->defaultImage = FIRST_ENTRY_INDEX;
|
||
|
+ config->defaultImage = newBootEntryIndex;
|
||
|
return;
|
||
|
- } else if ((newDefaultBootEntryIndex >= 0) && config->cfi->defaultIsIndex) {
|
||
|
- if (findEntryByIndex(config, newDefaultBootEntryIndex))
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Case 2: user picked an arbitrary index as the default boot entry */
|
||
|
+ if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX
|
||
|
+ && config->cfi->defaultIsIndex) {
|
||
|
+ indexToVerify = newDefaultBootEntryIndex;
|
||
|
+
|
||
|
+ /* user chose to make latest boot entry the default */
|
||
|
+ if (newDefaultBootEntryIndex == newBootEntryIndex) {
|
||
|
+ config->defaultImage = newBootEntryIndex;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* the user picks the default index based on the
|
||
|
+ * order of the bootloader configuration after
|
||
|
+ * modification; ensure we are checking for the
|
||
|
+ * existence of the correct entry */
|
||
|
+ if (newBootEntryIndex < newDefaultBootEntryIndex) {
|
||
|
+ if (!config->isModified)
|
||
|
+ indexToVerify--;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* verify the user selected index will exist */
|
||
|
+ if (findEntryByIndex(config, indexToVerify)) {
|
||
|
config->defaultImage = newDefaultBootEntryIndex;
|
||
|
- else
|
||
|
- config->defaultImage = NO_DEFAULT_ENTRY;
|
||
|
- return;
|
||
|
- } else if (defaultKernelPath) {
|
||
|
- i = 0;
|
||
|
- if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {
|
||
|
- config->defaultImage = i;
|
||
|
} else {
|
||
|
config->defaultImage = NO_DEFAULT_ENTRY;
|
||
|
- return;
|
||
|
}
|
||
|
- }
|
||
|
|
||
|
- /* defaultImage now points to what we'd like to use, but before any
|
||
|
- * order changes */
|
||
|
- if ((config->defaultImage == DEFAULT_SAVED) ||
|
||
|
- (config->defaultImage == DEFAULT_SAVED_GRUB2))
|
||
|
- /* default is set to saved, we don't want to change it */
|
||
|
return;
|
||
|
+ }
|
||
|
|
||
|
- if (config->defaultImage >= FIRST_ENTRY_INDEX)
|
||
|
- entry = findEntryByIndex(config, config->defaultImage);
|
||
|
- else
|
||
|
- entry = NULL;
|
||
|
+ /* handle cases where the index value may shift */
|
||
|
|
||
|
- if (entry && !entry->skip) {
|
||
|
- /* we can preserve the default */
|
||
|
- if (isUserSpecifiedKernelPath)
|
||
|
+ /* check validity of existing default or first-entry-found
|
||
|
+ selection */
|
||
|
+ if (defaultKernelPath) {
|
||
|
+ /* user requested first-entry-found */
|
||
|
+ if (!findEntryByPath(config, defaultKernelPath,
|
||
|
+ prefix, &firstKernelEntryIndex)) {
|
||
|
+ /* don't change default if can't find match */
|
||
|
+ config->defaultImage = NO_DEFAULT_ENTRY;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ config->defaultImage = firstKernelEntryIndex;
|
||
|
+
|
||
|
+ /* this is where we start looking for decrement later */
|
||
|
+ currentLookupIndex = config->defaultImage;
|
||
|
+
|
||
|
+ if (isAddingBootEntry && !config->isModified &&
|
||
|
+ (newBootEntryIndex < config->defaultImage)) {
|
||
|
+ /* increment because new entry added before default */
|
||
|
config->defaultImage++;
|
||
|
-
|
||
|
- /* count the number of entries erased before this one */
|
||
|
- for (j = 0; j < config->defaultImage; j++) {
|
||
|
- entry2 = findEntryByIndex(config, j);
|
||
|
- if (entry2->skip)
|
||
|
- config->defaultImage--;
|
||
|
}
|
||
|
- } else if (isUserSpecifiedKernelPath) {
|
||
|
- config->defaultImage = FIRST_ENTRY_INDEX;
|
||
|
} else {
|
||
|
- /* Either we just erased the default (or the default line was
|
||
|
- * bad to begin with) and didn't put a new one in. We'll use
|
||
|
- * the first valid image. */
|
||
|
+ /* use pre-existing default entry */
|
||
|
+ currentLookupIndex = config->defaultImage;
|
||
|
+
|
||
|
+ if (isAddingBootEntry
|
||
|
+ && (newBootEntryIndex <= config->defaultImage)) {
|
||
|
+ config->defaultImage++;
|
||
|
+
|
||
|
+ if (config->isModified) {
|
||
|
+ currentLookupIndex++;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* sanity check - is this entry index valid? */
|
||
|
+ bootEntry = findEntryByIndex(config, currentLookupIndex);
|
||
|
+
|
||
|
+ if ((bootEntry && bootEntry->skip) || !bootEntry) {
|
||
|
+ /* entry is to be skipped or is invalid */
|
||
|
+ if (isAddingBootEntry) {
|
||
|
+ config->defaultImage = newBootEntryIndex;
|
||
|
+ return;
|
||
|
+ }
|
||
|
newDefault =
|
||
|
findTemplate(config, prefix, &config->defaultImage, 1,
|
||
|
flags);
|
||
|
- if (!newDefault)
|
||
|
+ if (!newDefault) {
|
||
|
config->defaultImage = NO_DEFAULT_ENTRY;
|
||
|
+ }
|
||
|
+
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ currentLookupIndex--;
|
||
|
+
|
||
|
+ /* decrement index by the total number of entries deleted */
|
||
|
+
|
||
|
+ for (indexToVerify = currentLookupIndex;
|
||
|
+ indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) {
|
||
|
+
|
||
|
+ bootEntry = findEntryByIndex(config, indexToVerify);
|
||
|
+
|
||
|
+ if (bootEntry && bootEntry->skip) {
|
||
|
+ config->defaultImage--;
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -5265,7 +5320,8 @@ int main(int argc, const char **argv)
|
||
|
markRemovedImage(config, removeKernelPath, bootPrefix);
|
||
|
markRemovedImage(config, removeMBKernel, bootPrefix);
|
||
|
setDefaultImage(config, newKernelPath != NULL, defaultKernel,
|
||
|
- makeDefault, bootPrefix, flags, defaultIndex);
|
||
|
+ makeDefault, bootPrefix, flags, defaultIndex,
|
||
|
+ newIndex);
|
||
|
setFallbackImage(config, newKernelPath != NULL);
|
||
|
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
|
||
|
removeArgs, newMBKernelArgs, removeMBKernelArgs))
|
||
|
--
|
||
|
2.17.1
|
||
|
|