This patch adds code that gets lba and boot device information on SuSE systems, which is done by looking at the commands that were used to install grub on that system, and match information with grub's device.map file. Signed-off-by: Cleber Rosa <crosa@xxxxxxxxxx> --- grubby.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 232 insertions(+), 6 deletions(-) diff --git a/grubby.c b/grubby.c index 601ba8d..c664387 100644 --- a/grubby.c +++ b/grubby.c @@ -56,6 +56,16 @@ int debug = 0; /* Currently just for template debugging */ #define NOOP_OPCODE 0x90 #define JMP_SHORT_OPCODE 0xeb +/* + * This SuSE grub configuration file at this location is not your average + * grub configuration file, but instead the grub commands used to setup + * grub on that system. + */ +#define SUSE_GRUB_CONF "/etc/grub.conf" +#define SUSE_RELEASE_FILE "/etc/SuSE-release" +#define GRUB_DEVICE_MAP "/boot/grub/device.map" + + /* comments get lumped in with indention */ struct lineElement { char * item; @@ -1938,6 +1948,202 @@ void displayEntry(struct singleEntry * entry, const char * prefix, int index) { } } +int isSuseGrubConf(const char * path) { + FILE * grubConf; + char * line = NULL; + size_t len = 0; + + grubConf = fopen(path, "r"); + if (!grubConf) { + dbgPrintf("Could not open SuSE configuration file '%s'\n", + SUSE_GRUB_CONF); + return 1; + } + + if (getline(&line, &len, grubConf) == -1) { + dbgPrintf("Could not read line from file '%s'\n", + SUSE_GRUB_CONF); + return 1; + } + + if (strncmp(line, "setup", 5)) { + dbgPrintf("SuSE configuration file '%s' does not appear to be valid\n", + SUSE_GRUB_CONF); + return 1; + } + + free(line); + fclose(grubConf); + return 0; +} + +int suseGrubConfGetLba(const char * path, int * lbaPtr) { + FILE * grubConf; + char * line = NULL; + size_t len = 0; + + if (!path) return 1; + if (!lbaPtr) return 1; + + grubConf = fopen(path, "r"); + if (!grubConf) return 1; + + while (getline(&line, &len, grubConf) != -1) { + if (!strncmp(line, "setup", 5)) { + if (strstr(line, "--force-lba")) { + *lbaPtr = 1; + } else { + *lbaPtr = 0; + } + dbgPrintf("lba: %i\n", *lbaPtr); + break; + } + } + + free(line); + fclose(grubConf); + return 0; +} + +int suseGrubConfGetInstallDevice(const char * path, char ** devicePtr) { + FILE * grubConf; + char * line = NULL; + size_t len = 0; + char * lastParamPtr = NULL; + char * secLastParamPtr = NULL; + char installDeviceNumber = '\0'; + + if (!path) return 1; + if (!devicePtr) return 1; + + grubConf = fopen(path, "r"); + if (!grubConf) return 1; + + while (getline(&line, &len, grubConf) != -1) { + /* + * If this is a line with a valid setup command, it will contain + * the device grub will be installed to. + */ + if (!strncmp(line, "setup", 5)) { + + lastParamPtr = line + strlen(line); + + if (*--lastParamPtr == '\n') + *lastParamPtr = '\0'; + + /* Last parameter in grub may be an optional IMAGE_DEVICE */ + while (!isspace(*lastParamPtr)) + lastParamPtr--; + lastParamPtr++; + + secLastParamPtr = lastParamPtr - 2; + dbgPrintf("lastParamPtr: %s\n", lastParamPtr); + if (!strncmp(lastParamPtr, "(hd", 3)) + lastParamPtr += 3; + dbgPrintf("lastParamPtr: %c\n", *lastParamPtr); + + /* + * Second last parameter will point out if last parameter is + * either an IMAGE_DEVICE or INSTALL_DEVICE + */ + while (!isspace(*secLastParamPtr)) + secLastParamPtr--; + secLastParamPtr++; + + dbgPrintf("secLastParamPtr: %s\n", secLastParamPtr); + if (!strncmp(secLastParamPtr, "(hd", 3)) { + secLastParamPtr += 3; + dbgPrintf("secLastParamPtr: %c\n", *secLastParamPtr); + + installDeviceNumber = *secLastParamPtr; + } else { + installDeviceNumber = *lastParamPtr; + } + + *devicePtr = malloc(6); + snprintf(*devicePtr, 6, "(hd%c)", installDeviceNumber); + dbgPrintf("installDeviceNumber: %c\n", installDeviceNumber); + break; + } + } + + free(line); + fclose(grubConf); + return 0; +} + +int grubGetBootFromDeviceMap(const char * path, + const char * device, + char ** bootPtr) { + FILE * deviceMap; + char * line = NULL; + size_t len = 0; + char * devicePtr; + char * end; + + if (!path) return 1; + if (!device) return 1; + if (!bootPtr) return 1; + + deviceMap = fopen(path, "r"); + if (!deviceMap) return 1; + + while (getline(&line, &len, deviceMap) != -1) { + if (strncmp(line, "#", 1)) { + devicePtr = line; + while (isspace(*line)) + devicePtr++; + dbgPrintf("device: %s\n", devicePtr); + + if (!strncmp(devicePtr, device, strlen(device))) { + devicePtr += strlen(device); + while (isspace(*devicePtr)) + devicePtr++; + + end = strchr(devicePtr, '\n'); + if (end) + *end = '\0'; + + *bootPtr = strdup(devicePtr); + break; + } + } + } + + free(line); + fclose(deviceMap); + return 0; +} + +int suseGrubConfGetBoot(const char * path, char ** bootPtr) { + char * grubDevice; + + suseGrubConfGetInstallDevice(path, &grubDevice); + dbgPrintf("grubby installation device: %s\n", grubDevice); + + grubGetBootFromDeviceMap(GRUB_DEVICE_MAP, grubDevice, bootPtr); + dbgPrintf("boot: %s\n", *bootPtr); + + return 0; +} + +int parseSuseGrubConf(int * lbaPtr, char ** bootPtr) { + if (isSuseGrubConf(SUSE_GRUB_CONF)) return 1; + + if (lbaPtr) { + *lbaPtr = 0; + if (suseGrubConfGetLba(SUSE_GRUB_CONF, lbaPtr)) + return 1; + } + + if (bootPtr) { + *bootPtr = NULL; + suseGrubConfGetBoot(SUSE_GRUB_CONF, bootPtr); + } + + return 0; +} + int parseSysconfigGrub(int * lbaPtr, char ** bootPtr) { FILE * in; char buf[1024]; @@ -1988,11 +2194,19 @@ int parseSysconfigGrub(int * lbaPtr, char ** bootPtr) { void dumpSysconfigGrub(void) { char * boot; int lba; + int notOnSuse; - if (!parseSysconfigGrub(&lba, &boot)) { - if (lba) printf("lba\n"); - if (boot) printf("boot=%s\n", boot); + notOnSuse = access(SUSE_RELEASE_FILE, R_OK); + if (notOnSuse) { + if (parseSysconfigGrub(&lba, &boot)) + return; + } else { + if (parseSuseGrubConf(&lba, &boot)) + return; } + + if (lba) printf("lba\n"); + if (boot) printf("boot=%s\n", boot); } int displayInfo(struct grubConfig * config, char * kernel, @@ -2812,9 +3026,14 @@ int checkForGrub(struct grubConfig * config) { int fd; unsigned char bootSect[512]; char * boot; + int notOnSuse; - if (parseSysconfigGrub(NULL, &boot)) - return 0; + notOnSuse = access(SUSE_RELEASE_FILE, R_OK); + if (notOnSuse) { + if (parseSysconfigGrub(NULL, &boot)) return 0; + } else { + if (parseSuseGrubConf(NULL, &boot)) return 0; + } /* assume grub is not installed -- not an error condition */ if (!boot) @@ -2833,7 +3052,14 @@ int checkForGrub(struct grubConfig * config) { } close(fd); - return checkDeviceBootloader(boot, bootSect); + if (notOnSuse) + return checkDeviceBootloader(boot, bootSect); + else + /* + * The more elaborate checks do not work on SuSE. The checks done + * seem to be reasonble (at least for now), so just return success + */ + return 2; } int checkForExtLinux(struct grubConfig * config) { -- 1.7.6.5 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list