132 |
#define NEED_DEVTREE (1 << 6) |
#define NEED_DEVTREE (1 << 6) |
133 |
|
|
134 |
#define MAIN_DEFAULT (1 << 0) |
#define MAIN_DEFAULT (1 << 0) |
135 |
|
#define FIRST_ENTRY_INDEX 0 /* boot entry index value begin and increment |
136 |
|
from this initial value */ |
137 |
|
#define NO_DEFAULT_ENTRY -1 /* indicates that no specific default boot |
138 |
|
entry was set or currently exists */ |
139 |
#define DEFAULT_SAVED -2 |
#define DEFAULT_SAVED -2 |
140 |
#define DEFAULT_SAVED_GRUB2 -3 |
#define DEFAULT_SAVED_GRUB2 -3 |
141 |
|
|
681 |
int fallbackImage; /* just like defaultImage */ |
int fallbackImage; /* just like defaultImage */ |
682 |
int flags; |
int flags; |
683 |
struct configFileInfo *cfi; |
struct configFileInfo *cfi; |
684 |
|
int isModified; /* assumes only one entry added |
685 |
|
per invocation of grubby */ |
686 |
}; |
}; |
687 |
|
|
688 |
blkid_cache blkid; |
blkid_cache blkid; |
1302 |
cfg->theLines = NULL; |
cfg->theLines = NULL; |
1303 |
cfg->entries = NULL; |
cfg->entries = NULL; |
1304 |
cfg->fallbackImage = 0; |
cfg->fallbackImage = 0; |
1305 |
|
cfg->isModified = 0; |
1306 |
|
|
1307 |
/* copy everything we have */ |
/* copy everything we have */ |
1308 |
while (*head) { |
while (*head) { |
1622 |
*end == ' ' || *end == '\t')) |
*end == ' ' || *end == '\t')) |
1623 |
end++; |
end++; |
1624 |
if (*end) |
if (*end) |
1625 |
cfg->defaultImage = -1; |
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1626 |
} else if (defaultLine->numElements == 3) { |
} else if (defaultLine->numElements == 3) { |
1627 |
char *value = defaultLine->elements[2].item; |
char *value = defaultLine->elements[2].item; |
1628 |
while (*value && (*value == '"' || |
while (*value && (*value == '"' || |
1635 |
*end == ' ' || *end == '\t')) |
*end == ' ' || *end == '\t')) |
1636 |
end++; |
end++; |
1637 |
if (*end) |
if (*end) |
1638 |
cfg->defaultImage = -1; |
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1639 |
} |
} |
1640 |
} else if (cfi->defaultSupportSaved && |
} else if (cfi->defaultSupportSaved && |
1641 |
!strncmp(defaultLine->elements[1].item, "saved", |
!strncmp(defaultLine->elements[1].item, "saved", |
1645 |
cfg->defaultImage = |
cfg->defaultImage = |
1646 |
strtol(defaultLine->elements[1].item, &end, 10); |
strtol(defaultLine->elements[1].item, &end, 10); |
1647 |
if (*end) |
if (*end) |
1648 |
cfg->defaultImage = -1; |
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1649 |
} else if (defaultLine->numElements >= 2) { |
} else if (defaultLine->numElements >= 2) { |
1650 |
int i = 0; |
int i = 0; |
1651 |
while ((entry = findEntryByIndex(cfg, i))) { |
while ((entry = findEntryByIndex(cfg, i))) { |
1673 |
if (entry) { |
if (entry) { |
1674 |
cfg->defaultImage = i; |
cfg->defaultImage = i; |
1675 |
} else { |
} else { |
1676 |
cfg->defaultImage = -1; |
cfg->defaultImage = NO_DEFAULT_ENTRY; |
1677 |
} |
} |
1678 |
} |
} |
1679 |
} else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) { |
} else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) { |
1690 |
cfg->defaultImage = index; |
cfg->defaultImage = index; |
1691 |
} |
} |
1692 |
} else { |
} else { |
1693 |
cfg->defaultImage = 0; |
cfg->defaultImage = FIRST_ENTRY_INDEX; |
1694 |
} |
} |
1695 |
|
|
1696 |
return cfg; |
return cfg; |
1710 |
fprintf(out, "%sdefault%ssaved\n", indent, separator); |
fprintf(out, "%sdefault%ssaved\n", indent, separator); |
1711 |
else if (cfg->cfi->defaultIsSaved) { |
else if (cfg->cfi->defaultIsSaved) { |
1712 |
fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); |
fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); |
1713 |
if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) { |
if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) { |
1714 |
char *title; |
char *title; |
1715 |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
1716 |
line = getLineByType(LT_MENUENTRY, entry->lines); |
line = getLineByType(LT_MENUENTRY, entry->lines); |
1723 |
"saved_entry", title); |
"saved_entry", title); |
1724 |
} |
} |
1725 |
} |
} |
1726 |
} else if (cfg->defaultImage > -1) { |
} else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) { |
1727 |
if (cfg->cfi->defaultIsIndex) { |
if (cfg->cfi->defaultIsIndex) { |
1728 |
if (cfg->cfi->defaultIsVariable) { |
if (cfg->cfi->defaultIsVariable) { |
1729 |
fprintf(out, "%sset default=\"%d\"\n", indent, |
fprintf(out, "%sset default=\"%d\"\n", indent, |
2427 |
} |
} |
2428 |
} |
} |
2429 |
} |
} |
2430 |
} else if (cfg->defaultImage > -1) { |
} else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) { |
2431 |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
entry = findEntryByIndex(cfg, cfg->defaultImage); |
2432 |
if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { |
if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { |
2433 |
if (indexPtr) |
if (indexPtr) |
2501 |
entry->skip = 1; |
entry->skip = 1; |
2502 |
} |
} |
2503 |
|
|
2504 |
void setDefaultImage(struct grubConfig *config, int hasNew, |
void setDefaultImage(struct grubConfig *config, int isAddingBootEntry, |
2505 |
const char *defaultKernelPath, int newIsDefault, |
const char *defaultKernelPath, int newBootEntryIsDefault, |
2506 |
const char *prefix, int flags, int index) |
const char *prefix, int flags, |
2507 |
{ |
int newDefaultBootEntryIndex, int newBootEntryIndex) |
2508 |
struct singleEntry *entry, *entry2, *newDefault; |
{ |
2509 |
int i, j; |
struct singleEntry *bootEntry, *newDefault; |
2510 |
|
int indexToVerify, firstKernelEntryIndex, currentLookupIndex; |
2511 |
if (newIsDefault) { |
|
2512 |
config->defaultImage = 0; |
/* handle the two cases where the user explictly picks the default |
2513 |
return; |
* boot entry index as it would exist post-modification */ |
2514 |
} else if ((index >= 0) && config->cfi->defaultIsIndex) { |
|
2515 |
if (findEntryByIndex(config, index)) |
/* Case 1: user chose to make the latest boot entry the default */ |
2516 |
config->defaultImage = index; |
if (newBootEntryIsDefault) { |
2517 |
else |
config->defaultImage = newBootEntryIndex; |
|
config->defaultImage = -1; |
|
2518 |
return; |
return; |
2519 |
} else if (defaultKernelPath) { |
} |
2520 |
i = 0; |
|
2521 |
if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { |
/* Case 2: user picked an arbitrary index as the default boot entry */ |
2522 |
config->defaultImage = i; |
if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX |
2523 |
} else { |
&& config->cfi->defaultIsIndex) { |
2524 |
config->defaultImage = -1; |
indexToVerify = newDefaultBootEntryIndex; |
2525 |
|
|
2526 |
|
/* user chose to make latest boot entry the default */ |
2527 |
|
if (newDefaultBootEntryIndex == newBootEntryIndex) { |
2528 |
|
config->defaultImage = newBootEntryIndex; |
2529 |
return; |
return; |
2530 |
} |
} |
|
} |
|
2531 |
|
|
2532 |
/* defaultImage now points to what we'd like to use, but before any |
/* the user picks the default index based on the |
2533 |
* order changes */ |
* order of the bootloader configuration after |
2534 |
if ((config->defaultImage == DEFAULT_SAVED) || |
* modification; ensure we are checking for the |
2535 |
(config->defaultImage == DEFAULT_SAVED_GRUB2)) |
* existence of the correct entry */ |
2536 |
/* default is set to saved, we don't want to change it */ |
if (newBootEntryIndex < newDefaultBootEntryIndex) { |
2537 |
|
if (!config->isModified) |
2538 |
|
indexToVerify--; |
2539 |
|
} |
2540 |
|
|
2541 |
|
/* verify the user selected index will exist */ |
2542 |
|
if (findEntryByIndex(config, indexToVerify)) { |
2543 |
|
config->defaultImage = newDefaultBootEntryIndex; |
2544 |
|
} else { |
2545 |
|
config->defaultImage = NO_DEFAULT_ENTRY; |
2546 |
|
} |
2547 |
|
|
2548 |
return; |
return; |
2549 |
|
} |
2550 |
|
|
2551 |
if (config->defaultImage > -1) |
/* handle cases where the index value may shift */ |
|
entry = findEntryByIndex(config, config->defaultImage); |
|
|
else |
|
|
entry = NULL; |
|
2552 |
|
|
2553 |
if (entry && !entry->skip) { |
/* check validity of existing default or first-entry-found |
2554 |
/* we can preserve the default */ |
selection */ |
2555 |
if (hasNew) |
if (defaultKernelPath) { |
2556 |
config->defaultImage++; |
/* user requested first-entry-found */ |
2557 |
|
if (!findEntryByPath(config, defaultKernelPath, |
2558 |
|
prefix, &firstKernelEntryIndex)) { |
2559 |
|
/* don't change default if can't find match */ |
2560 |
|
config->defaultImage = NO_DEFAULT_ENTRY; |
2561 |
|
return; |
2562 |
|
} |
2563 |
|
|
2564 |
|
config->defaultImage = firstKernelEntryIndex; |
2565 |
|
|
2566 |
|
/* this is where we start looking for decrement later */ |
2567 |
|
currentLookupIndex = config->defaultImage; |
2568 |
|
|
2569 |
/* count the number of entries erased before this one */ |
if (isAddingBootEntry && !config->isModified && |
2570 |
for (j = 0; j < config->defaultImage; j++) { |
(newBootEntryIndex < config->defaultImage)) { |
2571 |
entry2 = findEntryByIndex(config, j); |
/* increment because new entry added before default */ |
2572 |
if (entry2->skip) |
config->defaultImage++; |
|
config->defaultImage--; |
|
2573 |
} |
} |
|
} else if (hasNew) { |
|
|
config->defaultImage = 0; |
|
2574 |
} else { |
} else { |
2575 |
/* Either we just erased the default (or the default line was |
/* use pre-existing default entry */ |
2576 |
* bad to begin with) and didn't put a new one in. We'll use |
currentLookupIndex = config->defaultImage; |
2577 |
* the first valid image. */ |
|
2578 |
|
if (isAddingBootEntry |
2579 |
|
&& (newBootEntryIndex <= config->defaultImage)) { |
2580 |
|
config->defaultImage++; |
2581 |
|
|
2582 |
|
if (config->isModified) { |
2583 |
|
currentLookupIndex++; |
2584 |
|
} |
2585 |
|
} |
2586 |
|
} |
2587 |
|
|
2588 |
|
/* sanity check - is this entry index valid? */ |
2589 |
|
bootEntry = findEntryByIndex(config, currentLookupIndex); |
2590 |
|
|
2591 |
|
if ((bootEntry && bootEntry->skip) || !bootEntry) { |
2592 |
|
/* entry is to be skipped or is invalid */ |
2593 |
|
if (isAddingBootEntry) { |
2594 |
|
config->defaultImage = newBootEntryIndex; |
2595 |
|
return; |
2596 |
|
} |
2597 |
newDefault = |
newDefault = |
2598 |
findTemplate(config, prefix, &config->defaultImage, 1, |
findTemplate(config, prefix, &config->defaultImage, 1, |
2599 |
flags); |
flags); |
2600 |
if (!newDefault) |
if (!newDefault) { |
2601 |
config->defaultImage = -1; |
config->defaultImage = NO_DEFAULT_ENTRY; |
2602 |
|
} |
2603 |
|
|
2604 |
|
return; |
2605 |
|
} |
2606 |
|
|
2607 |
|
currentLookupIndex--; |
2608 |
|
|
2609 |
|
/* decrement index by the total number of entries deleted */ |
2610 |
|
|
2611 |
|
for (indexToVerify = currentLookupIndex; |
2612 |
|
indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) { |
2613 |
|
|
2614 |
|
bootEntry = findEntryByIndex(config, indexToVerify); |
2615 |
|
|
2616 |
|
if (bootEntry && bootEntry->skip) { |
2617 |
|
config->defaultImage--; |
2618 |
|
} |
2619 |
} |
} |
2620 |
} |
} |
2621 |
|
|
4787 |
} |
} |
4788 |
|
|
4789 |
if (updateImage(config, indexs, prefix, newKernelArgs, NULL, |
if (updateImage(config, indexs, prefix, newKernelArgs, NULL, |
4790 |
newMBKernelArgs, NULL)) |
newMBKernelArgs, NULL)) { |
4791 |
|
config->isModified = 1; |
4792 |
return 1; |
return 1; |
4793 |
|
} |
4794 |
|
|
4795 |
return 0; |
return 0; |
4796 |
} |
} |
5242 |
struct singleEntry *entry; |
struct singleEntry *entry; |
5243 |
char *rootspec; |
char *rootspec; |
5244 |
|
|
5245 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5246 |
return 0; |
return 0; |
5247 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5248 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5249 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5250 |
entry = findEntryByIndex(config, config->defaultImage); |
entry = findEntryByIndex(config, config->defaultImage); |
5251 |
if (!entry) |
if (!entry) |
5252 |
return 0; |
return 0; |
5269 |
struct singleLine *line; |
struct singleLine *line; |
5270 |
struct singleEntry *entry; |
struct singleEntry *entry; |
5271 |
|
|
5272 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5273 |
return 0; |
return 0; |
5274 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5275 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5276 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5277 |
entry = findEntryByIndex(config, config->defaultImage); |
entry = findEntryByIndex(config, config->defaultImage); |
5278 |
if (!entry) |
if (!entry) |
5279 |
return 0; |
return 0; |
5303 |
return 0; |
return 0; |
5304 |
|
|
5305 |
} else if (displayDefaultIndex) { |
} else if (displayDefaultIndex) { |
5306 |
if (config->defaultImage == -1) |
if (config->defaultImage == NO_DEFAULT_ENTRY) |
5307 |
return 0; |
return 0; |
5308 |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
if (config->defaultImage == DEFAULT_SAVED_GRUB2 && |
5309 |
cfi->defaultIsSaved) |
cfi->defaultIsSaved) |
5310 |
config->defaultImage = 0; |
config->defaultImage = FIRST_ENTRY_INDEX; |
5311 |
printf("%i\n", config->defaultImage); |
printf("%i\n", config->defaultImage); |
5312 |
return 0; |
return 0; |
5313 |
|
|
5323 |
markRemovedImage(config, removeKernelPath, bootPrefix); |
markRemovedImage(config, removeKernelPath, bootPrefix); |
5324 |
markRemovedImage(config, removeMBKernel, bootPrefix); |
markRemovedImage(config, removeMBKernel, bootPrefix); |
5325 |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, |
setDefaultImage(config, newKernelPath != NULL, defaultKernel, |
5326 |
makeDefault, bootPrefix, flags, defaultIndex); |
makeDefault, bootPrefix, flags, defaultIndex, |
5327 |
|
newIndex); |
5328 |
setFallbackImage(config, newKernelPath != NULL); |
setFallbackImage(config, newKernelPath != NULL); |
5329 |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, |
5330 |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) |
removeArgs, newMBKernelArgs, removeMBKernelArgs)) |