46 |
#define dbgPrintf(format, args...) |
#define dbgPrintf(format, args...) |
47 |
#endif |
#endif |
48 |
|
|
49 |
|
int debug = 0; /* Currently just for template debugging */ |
50 |
|
|
51 |
#define _(A) (A) |
#define _(A) (A) |
52 |
|
|
53 |
#define MAX_EXTRA_INITRDS 16 /* code segment checked by --bootloader-probe */ |
#define MAX_EXTRA_INITRDS 16 /* code segment checked by --bootloader-probe */ |
876 |
cfg->secondaryIndent = strdup(line->indent); |
cfg->secondaryIndent = strdup(line->indent); |
877 |
} |
} |
878 |
|
|
879 |
if (isEntryStart(line, cfi)) { |
if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) { |
880 |
sawEntry = 1; |
sawEntry = 1; |
881 |
if (!entry) { |
if (!entry) { |
882 |
cfg->entries = malloc(sizeof(*entry)); |
cfg->entries = malloc(sizeof(*entry)); |
1340 |
return NULL; |
return NULL; |
1341 |
} |
} |
1342 |
|
|
1343 |
|
void printEntry(struct singleEntry * entry) { |
1344 |
|
int i; |
1345 |
|
struct singleLine * line; |
1346 |
|
|
1347 |
|
for (line = entry->lines; line; line = line->next) { |
1348 |
|
fprintf(stderr, "DBG: %s", line->indent); |
1349 |
|
for (i = 0; i < line->numElements; i++) { |
1350 |
|
fprintf(stderr, "%s%s", |
1351 |
|
line->elements[i].item, line->elements[i].indent); |
1352 |
|
} |
1353 |
|
fprintf(stderr, "\n"); |
1354 |
|
} |
1355 |
|
} |
1356 |
|
|
1357 |
|
void notSuitablePrintf(struct singleEntry * entry, const char *fmt, ...) |
1358 |
|
{ |
1359 |
|
va_list argp; |
1360 |
|
|
1361 |
|
if (!debug) |
1362 |
|
return; |
1363 |
|
|
1364 |
|
va_start(argp, fmt); |
1365 |
|
fprintf(stderr, "DBG: Image entry failed: "); |
1366 |
|
vfprintf(stderr, fmt, argp); |
1367 |
|
printEntry(entry); |
1368 |
|
va_end(argp); |
1369 |
|
} |
1370 |
|
|
1371 |
|
#define beginswith(s, c) ((s) && (s)[0] == (c)) |
1372 |
|
|
1373 |
|
static int endswith(const char *s, char c) |
1374 |
|
{ |
1375 |
|
int slen; |
1376 |
|
|
1377 |
|
if (!s && !s[0]) |
1378 |
|
return 0; |
1379 |
|
slen = strlen(s) - 1; |
1380 |
|
|
1381 |
|
return s[slen] == c; |
1382 |
|
} |
1383 |
|
|
1384 |
int suitableImage(struct singleEntry * entry, const char * bootPrefix, |
int suitableImage(struct singleEntry * entry, const char * bootPrefix, |
1385 |
int skipRemoved, int flags) { |
int skipRemoved, int flags) { |
1386 |
struct singleLine * line; |
struct singleLine * line; |
1390 |
char * rootspec; |
char * rootspec; |
1391 |
char * rootdev; |
char * rootdev; |
1392 |
|
|
1393 |
if (skipRemoved && entry->skip) return 0; |
if (skipRemoved && entry->skip) { |
1394 |
|
notSuitablePrintf(entry, "marked to skip\n"); |
1395 |
|
return 0; |
1396 |
|
} |
1397 |
|
|
1398 |
line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); |
line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); |
1399 |
if (!line || line->numElements < 2) return 0; |
if (!line) { |
1400 |
|
notSuitablePrintf(entry, "no line found\n"); |
1401 |
|
return 0; |
1402 |
|
} |
1403 |
|
if (line->numElements < 2) { |
1404 |
|
notSuitablePrintf(entry, "line has only %d elements\n", |
1405 |
|
line->numElements); |
1406 |
|
return 0; |
1407 |
|
} |
1408 |
|
|
1409 |
if (flags & GRUBBY_BADIMAGE_OKAY) return 1; |
if (flags & GRUBBY_BADIMAGE_OKAY) return 1; |
1410 |
|
|
1411 |
fullName = alloca(strlen(bootPrefix) + |
fullName = alloca(strlen(bootPrefix) + |
1412 |
strlen(line->elements[1].item) + 1); |
strlen(line->elements[1].item) + 1); |
1413 |
rootspec = getRootSpecifier(line->elements[1].item); |
rootspec = getRootSpecifier(line->elements[1].item); |
1414 |
sprintf(fullName, "%s%s", bootPrefix, |
int rootspec_offset = rootspec ? strlen(rootspec) : 0; |
1415 |
line->elements[1].item + (rootspec ? strlen(rootspec) : 0)); |
int hasslash = endswith(bootPrefix, '/') || |
1416 |
if (access(fullName, R_OK)) return 0; |
beginswith(line->elements[1].item + rootspec_offset, '/'); |
1417 |
|
sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", |
1418 |
|
line->elements[1].item + rootspec_offset); |
1419 |
|
if (access(fullName, R_OK)) { |
1420 |
|
notSuitablePrintf(entry, "access to %s failed\n", fullName); |
1421 |
|
return 0; |
1422 |
|
} |
1423 |
for (i = 2; i < line->numElements; i++) |
for (i = 2; i < line->numElements; i++) |
1424 |
if (!strncasecmp(line->elements[i].item, "root=", 5)) break; |
if (!strncasecmp(line->elements[i].item, "root=", 5)) break; |
1425 |
if (i < line->numElements) { |
if (i < line->numElements) { |
1437 |
line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines); |
line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines); |
1438 |
|
|
1439 |
/* failed to find one */ |
/* failed to find one */ |
1440 |
if (!line) return 0; |
if (!line) { |
1441 |
|
notSuitablePrintf(entry, "no line found\n"); |
1442 |
|
return 0; |
1443 |
|
} |
1444 |
|
|
1445 |
for (i = 1; i < line->numElements; i++) |
for (i = 1; i < line->numElements; i++) |
1446 |
if (!strncasecmp(line->elements[i].item, "root=", 5)) break; |
if (!strncasecmp(line->elements[i].item, "root=", 5)) break; |
1447 |
if (i < line->numElements) |
if (i < line->numElements) |
1448 |
dev = line->elements[i].item + 5; |
dev = line->elements[i].item + 5; |
1449 |
else { |
else { |
1450 |
|
notSuitablePrintf(entry, "no root= entry found\n"); |
1451 |
/* it failed too... can't find root= */ |
/* it failed too... can't find root= */ |
1452 |
return 0; |
return 0; |
1453 |
} |
} |
1455 |
} |
} |
1456 |
|
|
1457 |
dev = getpathbyspec(dev); |
dev = getpathbyspec(dev); |
1458 |
if (!dev) |
if (!getpathbyspec(dev)) { |
1459 |
|
notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev); |
1460 |
return 0; |
return 0; |
1461 |
|
} else |
1462 |
|
dev = getpathbyspec(dev); |
1463 |
|
|
1464 |
rootdev = findDiskForRoot(); |
rootdev = findDiskForRoot(); |
1465 |
if (!rootdev) |
if (!rootdev) { |
1466 |
|
notSuitablePrintf(entry, "can't find root device\n"); |
1467 |
return 0; |
return 0; |
1468 |
|
} |
1469 |
|
|
1470 |
if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) { |
if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) { |
1471 |
|
notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n", |
1472 |
|
getuuidbydev(rootdev), getuuidbydev(dev)); |
1473 |
free(rootdev); |
free(rootdev); |
1474 |
return 0; |
return 0; |
1475 |
} |
} |
1476 |
|
|
1477 |
if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) { |
if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) { |
1478 |
|
notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n", |
1479 |
|
getuuidbydev(rootdev), getuuidbydev(dev)); |
1480 |
free(rootdev); |
free(rootdev); |
1481 |
return 0; |
return 0; |
1482 |
} |
} |
3033 |
} |
} |
3034 |
} else if (tmplLine->type == LT_ECHO) { |
} else if (tmplLine->type == LT_ECHO) { |
3035 |
requote(tmplLine, config->cfi); |
requote(tmplLine, config->cfi); |
3036 |
|
static const char *prefix = "'Loading "; |
3037 |
if (tmplLine->numElements > 1 && |
if (tmplLine->numElements > 1 && |
3038 |
strstr(tmplLine->elements[1].item, "'Loading Linux ")) { |
strstr(tmplLine->elements[1].item, prefix) && |
3039 |
char *prefix = "'Loading "; |
masterLine->next && masterLine->next->type == LT_KERNEL) { |
3040 |
char *newTitle = malloc(strlen(prefix) + |
char *newTitle = malloc(strlen(prefix) + |
3041 |
strlen(newKernelTitle) + 2); |
strlen(newKernelTitle) + 2); |
3042 |
|
|
3265 |
"the kernel referenced by the default image does not exist, " |
"the kernel referenced by the default image does not exist, " |
3266 |
"the first linux entry whose kernel does exist is used as the " |
"the first linux entry whose kernel does exist is used as the " |
3267 |
"template"), NULL }, |
"template"), NULL }, |
3268 |
|
{ "debug", 0, 0, &debug, 0, |
3269 |
|
_("print debugging information for failures") }, |
3270 |
{ "default-kernel", 0, 0, &displayDefault, 0, |
{ "default-kernel", 0, 0, &displayDefault, 0, |
3271 |
_("display the path of the default kernel") }, |
_("display the path of the default kernel") }, |
3272 |
{ "default-index", 0, 0, &displayDefaultIndex, 0, |
{ "default-index", 0, 0, &displayDefaultIndex, 0, |