Aron Griffis
2006-Jun-29 21:42 UTC
[Fedora-xen] [PATCH 0 of 6] elilo multiboot support (take 2)
The following patches give grubby the ability to manipulate multiboot-capable elilo.conf. Fedora''s elilo already contains the support, these patches simply teach grubby to take advantage of it. These patches are an enabler for using Xen on ia64 with Fedora. This is a resend, with improvements, of the patches sent earlier. See https://www.redhat.com/archives/fedora-xen/2006-June/msg00068.html The improvements include: - general test suite improvements - grubby builds with each patch in succession - updates to the test suite for elilo multiboot - fixes to grubby.c to fix regressions introduced by the previous patches, when I hadn''t noticed the existence of the regression test suite... Regards, Aron
# HG changeset patch # User agriffis@cheo.zko.hp.com # Node ID 8bbf845cad0dc1774c348f036d4eaa0365aef7e9 # Parent 447ac07ef71dc6bb49376f5b0164823a8e8a38e0 Improve the test suite - By default, run all the tests, regardless of architecture. Since the test suite calls grubby and not the bootloaders themselves, there''s no reason to be selective. - Add command-line parsing: -b B --bootloader=B Test bootloader B instead of all -h --help Show this help message -v --verbose Verbose output --version Show version information - Run parse/write checks on all bootloaders instead of just grub and lilo - Print statistics at the end of the run - NB: These changes reveal that yaboot parsing has some issues. Additionally the symlink test now returns failure, which wasn''t being detected properly before. So... current test results are: 112 (93%) tests passed, 8 (6%) tests failed Signed-off-by: Aron Griffis <aron@hp.com> test.sh | 308 ++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 165 insertions(+), 143 deletions(-) diff -r 447ac07ef71d -r 8bbf845cad0d grubby/test.sh --- a/grubby/test.sh Fri Jun 23 09:01:37 2006 -0400 +++ b/grubby/test.sh Thu Jun 29 12:21:58 2006 -0400 @@ -1,132 +1,150 @@ #!/bin/bash - -ARCH=$(uname -m) - -elilotest="" -lilotest="" -grubtest="" -zipltest="" -yaboottest="" - -case "$ARCH" in - i?86) - lilotest="yes" - grubtest="yes" - ;; - x86_64) - lilotest="yes" - grubtest="yes" - ;; - ppc*) - yaboottest="yes" - ;; - s390*) - zipltest="yes" - ;; - *) - echo "Not running any tests for $ARCH" - exit 0 -esac - -export MALLOC_CHECK_=2 - -RESULT=0 - -oneTest () { - mode=$1 - cfg=test/$2 - correct=test/results/$3 - shift; shift; shift - ./grubby $mode --bad-image-okay -c $cfg -o - "$@" | cmp $correct > /dev/null - - if [ $? != 0 ]; then +# +# test.sh -- grubby regression tests +# + +#---------------------------------------------------------------------- +# Global vars +#---------------------------------------------------------------------- + +read dum1 version dum2 <<<''$Revision: 0.0 $'' +cmd=${0##*/} +opt_bootloader=* +opt_verbose=false +read -d '''' usage <<EOT +usage: test.sh [ -hv ] + + -b B --bootloader=B Test bootloader B instead of all + -h --help Show this help message + -v --verbose Verbose output + --version Show version information +EOT +declare -i pass=0 fail=0 +testing+ +#---------------------------------------------------------------------- +# Functions +#---------------------------------------------------------------------- + +oneTest() { + typeset mode=$1 cfg=test/$2 correct=test/results/$3 + shift 3 + + echo "$testing ... $mode $cfg $correct" + runme=( ./grubby "$mode" --bad-image-okay -c "$cfg" -o - "$@" ) + if "${runme[@]}" | cmp "$correct" > /dev/null; then + (( pass++ )) + if $opt_verbose; then + echo ------------------------------------------------------------- + echo -n "PASS: " + printf "%q " "${runme[@]}"; echo + "${runme[@]}" | diff -U30 "$cfg" - + echo + fi + else + (( fail++ )) echo ------------------------------------------------------------- - echo FAILURE: $cfg $correct "$@" - echo -n ./grubby $mode --bad-image-okay -c $cfg -o - - for arg in "$@"; do - echo -n " \"$arg\"" - done - echo "" - ./grubby $mode --bad-image-okay -c $cfg -o - "$@" | diff -u $correct -; - RESULT=1 + echo -n "FAIL: " + printf "%q " "${runme[@]}"; echo + "${runme[@]}" | diff -U30 "$correct" - + echo fi } -liloTest() { - if [ -z "$lilotest" ]; then echo "skipping LILO test" ; return; fi - oneTest --lilo "$@" -} - -eliloTest() { - if [ -z "$elilotest" ]; then echo "skipping ELILO test" ; return; fi - oneTest --elilo "$@" -} - -grubTest() { - if [ -z "$grubtest" ]; then echo "skipping GRUB test" ; return; fi - oneTest --grub "$@" -} - -yabootTest() { - if [ -z "$yaboottest" ]; then echo "skipping YABOOT test" ; return; fi - oneTest --yaboot "$@" -} - -ziplTest() { - if [ -z "$zipltest" ]; then echo "skipping Z/IPL test" ; return; fi - oneTest --zipl "$@" -} - -echo "Parse/write comparison..." -for n in $(cd test; echo grub.[0-9]*); do - grubTest $n ../$n --remove-kernel 1234 -done - -for n in $(cd test; echo lilo.[0-9]*); do - liloTest $n ../$n --remove-kernel 1234 -done - -echo "Permission preservation..." -cp test/grub.1 grub-test -chmod 0614 grub-test -touch -t 200301010101.00 grub-test -time=$(ls -l grub-test | awk ''{ print $6 " " $7 " "$8}'') -perm=$(ls -l grub-test | awk ''{print $1}'') -./grubby --grub --add-kernel bar --title title -c grub-test -newtime=$(ls -l grub-test | awk ''{ print $6 " " $7 " "$8}'') -newperm=$(ls -l grub-test | awk ''{print $1}'') -if [ "$time" == "$newtime" -o "$perm" != "$newperm" ]; then - echo " failed ($perm $newperm)"; -fi -rm -f grub-test - -cp test/lilo.1 lilo-test -chmod 0614 lilo-test -touch -t 200301010101.00 lilo-test -time=$(ls -l lilo-test | awk ''{ print $6 " " $7 " "$8}'') -perm=$(ls -l lilo-test | awk ''{print $1}'') -./grubby --lilo --add-kernel bar --title title -c lilo-test -newtime=$(ls -l lilo-test | awk ''{ print $6 " " $7 " "$8}'') -newperm=$(ls -l lilo-test | awk ''{print $1}'') -if [ "$time" == "$newtime" -o "$perm" != "$newperm" ]; then - echo " failed ($perm $newperm)"; -fi -rm -f lilo-test - -echo "Following symlinks..." -cp test/grub.1 grub-test -ln -s grub-test mytest -./grubby --grub --add-kernel bar --title title -c mytest -if [ ! -L mytest ]; then - echo " failed (not a symlink)" -fi -target=$(ls -l mytest | awk ''{ print $11 }'') -if [ "$target" != grub-test ]; then - echo " failed (wrong target)" -fi -rm -f grub-test mytest - -echo "GRUB default directive..." +# generate convenience functions +for b in $(./grubby --help | \ + sed -n ''s/^.*--\([^ ]*\) *configure \1 bootloader$/\1/p''); do + eval "${b}Test() { [[ \"$b\" == \$opt_bootloader ]] && oneTest --$b \"\$@\"; }" +done + +#---------------------------------------------------------------------- +# Main +#---------------------------------------------------------------------- + +# Use /usr/bin/getopt which supports GNU-style long options +args=$(getopt -o b:hv --long bootloader,help,verbose,version -n "$cmd" -- "$@") || exit +eval set -- "$args" +while true; do + case $1 in + -b|--bootloader) opt_bootloader=$2; shift 2 ;; + -h|--help) echo "$usage"; exit 0 ;; + -v|--verbose) opt_verbose=true; shift ;; + --version) echo "$cmd $version"; exit 0 ;; + --) shift; break ;; + *) echo "failed to process cmdline args" >&2; exit 1 ;; + esac +done + +export MALLOC_CHECK_=2 + +testing="Parse/write comparison" +for n in test/*.[0-9]*; do + n=${n#*/} # remove test/ + b=${n%.*} # remove suffix + [[ $b == $opt_bootloader ]] || continue + ${b}Test $n ../$n --remove-kernel 1234 +done + +testing="Permission preservation" +unset b +for n in test/*.[0-9]*; do + n=${n#*/} # remove test/ + [[ ${n%.*} == "$b" ]] && continue + b=${n%.*} # remove suffix + [[ $b == $opt_bootloader ]] || continue + + echo "$testing ... --$b" + + cp test/$n ${b}-test + chmod 0614 ${b}-test + touch -t 200301010101.00 ${b}-test + time=$(ls -l ${b}-test | awk ''{ print $6 " " $7 " "$8}'') + perm=$(ls -l ${b}-test | awk ''{print $1}'') + ./grubby --${b} --add-kernel bar --title title -c ${b}-test + if [[ $? != 0 ]]; then + echo " FAIL (grubby returned non-zero)" + (( fail++ )) + elif newtime=$(ls -l ${b}-test | awk ''{ print $6 " " $7 " "$8}'') && \ + newperm=$(ls -l ${b}-test | awk ''{print $1}'') && \ + [[ $time == "$newtime" || $perm != "$newperm" ]] + then + echo " FAIL ($perm $newperm)"; + (( fail++ )) + else + (( pass++ )) + fi + rm -f ${b}-test +done + +testing="Following symlinks" +unset b +for n in test/*.[0-9]*; do + n=${n#*/} # remove test/ + [[ ${n%.*} == "$b" ]] && continue + b=${n%.*} # remove suffix + [[ $b == $opt_bootloader ]] || continue + + echo "$testing ... --$b" + + cp test/${b}.1 ${b}-test + ln -s ${b}-test mytest + ./grubby --${b} --add-kernel bar --title title -c mytest + if [[ $? != 0 ]]; then + echo " failed (grubby returned non-zero)" + (( fail++ )) + elif [[ ! -L mytest ]]; then + echo " failed (not a symlink)" + (( fail++ )) + elif target=$(readlink mytest) && [[ $target != "${b}-test" ]]; then + echo " failed (wrong target)" + (( fail++ )) + else + (( pass++ )) + fi + rm -f ${b}-test mytest +done + +testing="GRUB default directive" grubTest grub.1 default/g1.1 --boot-filesystem=/boot --add-kernel /boot/new-kernel --title Some_Title grubTest grub.1 default/g1.2 --boot-filesystem=/boot --add-kernel /boot/new-kernel --title Some_Title --make-default grubTest grub.3 default/g3.1 --boot-filesystem=/boot --set-default=/boot/vmlinuz-2.4.7-2 @@ -135,7 +153,7 @@ grubTest grub.4 default/g4.2 --boot-file grubTest grub.4 default/g4.2 --boot-filesystem=/ --set-default=/boot/vmlinuz-2.4.7-ac3 --remove-kernel /boot/vmlinuz-2.4.7-2.5 --add-kernel=/boot/new-kernel --copy-default --title New_Title grubTest grub.6 default/g6.1 --remove-kernel=/boot/vmlinuz-2.4.7-2.9 --boot-filesystem=/ -echo "LILO default directive..." +testing="LILO default directive" liloTest lilo.1 default/l1.1 --set-default=/boot/vmlinuz-2.4.18-4 liloTest lilo.1 default/l1.2 --remove-kernel=/boot/vmlinuz-2.4.18-4smp liloTest lilo.1 default/l1.3 --add-kernel /boot/kernel --title label \ @@ -143,11 +161,11 @@ liloTest lilo.1 default/l1.4 --add-kerne liloTest lilo.1 default/l1.4 --add-kernel /boot/kernel --title label \ --copy-default --make-default -echo "Z/IPL default directive..." +testing="Z/IPL default directive" ziplTest zipl.1 default/z1.1 --add-kernel /boot/new-kernel --title test ziplTest zipl.1 default/z1.2 --add-kernel /boot/new-kernel --title test --make-default -echo "GRUB fallback directive..." +testing="GRUB fallback directive" grubTest grub.5 fallback/g5.1 --remove-kernel=/boot/vmlinuz-2.4.7-ac3 \ --boot-filesystem=/ grubTest grub.5 fallback/g5.2 --remove-kernel=/boot/vmlinuz-2.4.7-2.5 \ @@ -156,13 +174,13 @@ grubTest grub.5 fallback/g5.3 --remove-k --boot-filesystem=/ --copy-default --add-kernel=/boot/new-kernel \ --title="Some_Title" -echo "GRUB new kernel argument handling..." +testing="GRUB new kernel argument handling" grubTest grub.1 args/g1.1 --boot-filesystem=/boot \ --add-kernel=/boot/foo --title=some_title --args="1234" --copy-default grubTest grub.1 args/g1.2 --boot-filesystem=/boot \ --add-kernel=/boot/foo --title=some_title --args="1234" -echo "GRUB remove kernel..." +testing="GRUB remove kernel" grubTest grub.7 remove/g7.1 --boot-filesystem=/ \ --remove-kernel=/boot/vmlinuz-2.4.7-2.5 grubTest grub.3 remove/g3.1 --boot-filesystem=/ \ @@ -170,16 +188,16 @@ grubTest grub.9 remove/g9.1 --boot-files grubTest grub.9 remove/g9.1 --boot-filesystem=/boot \ --remove-kernel=/boot/vmlinuz-2.4.7-2 -echo "YABOOT remove kernel..." +testing="YABOOT remove kernel" yabootTest yaboot.1 remove/y1.1 --boot-filesystem=/ --remove-kernel=DEFAULT yabootTest yaboot.1 remove/y1.2 --boot-filesystem=/ --remove-kernel=/boot/vmlinuz-2.5.50-eepro yabootTest yaboot.2 remove/y2.1 --boot-filesystem=/ --remove-kernel=/boot/vmlinux-2.5.50 -echo "Z/IPL remove kernel..." +testing="Z/IPL remove kernel" ziplTest zipl.1 remove/z1.1 --remove-kernel=/boot/vmlinuz-2.4.9-38 ziplTest zipl.1 remove/z1.2 --remove-kernel=DEFAULT -echo "GRUB update kernel argument handling..." +testing="GRUB update kernel argument handling" grubTest grub.1 updargs/g1.1 --update-kernel=DEFAULT --args="root=/dev/hda1" grubTest grub.1 updargs/g1.2 --update-kernel=DEFAULT \ --args="root=/dev/hda1 hda=ide-scsi root=/dev/hda2" @@ -209,7 +227,7 @@ grubTest grub.11 updargs/g11.2 --boot-fi --update-kernel=/vmlinuz-2.4.7-2smp \ --args "ro root=LABEL=/ single" -echo "LILO update kernel argument handling..." +testing="LILO update kernel argument handling" liloTest lilo.1 updargs/l1.1 --update-kernel=/boot/vmlinuz-2.4.18-4 \ --args="root=/dev/md1" liloTest lilo.1 updargs/l1.2 --update-kernel=/boot/vmlinuz-2.4.18-4smp \ @@ -223,7 +241,7 @@ liloTest lilo.3 updargs/l3.2 --update-ke liloTest lilo.3 updargs/l3.2 --update-kernel=ALL \ --remove-args="single" --args "root=/dev/hda2" -echo "LILO add kernel..." +testing="LILO add kernel" liloTest lilo.4 add/l4.1 --add-kernel=/boot/new-kernel.img --title="title" \ --copy-default --boot-filesystem=/boot liloTest lilo.4 add/l4.2 --add-kernel=/boot/new-kernel.img --title="linux" \ @@ -238,7 +256,7 @@ liloTest lilo.6 add/l6.2 --add-kernel=/b --initrd=/boot/new-initrd --copy-default --boot-filesystem=/boot --remove-kernel "TITLE=linux" -echo "GRUB add kernel..." +testing="GRUB add kernel" grubTest grub.1 add/g1.1 --add-kernel=/boot/new-kernel.img --title=''title'' \ --initrd=/boot/new-initrd --boot-filesystem=/ grubTest grub.1 add/g1.2 --add-kernel=/boot/new-kernel.img --title=''title'' \ @@ -260,19 +278,19 @@ grubTest grub.11 add/g11.1 --add-kernel --initrd=/boot/new-initrd --boot-filesystem=/boot --copy-default \ --args=''console=tty0 console=ttyS1,9600n81 single'' -echo "YABOOT add kernel..." +testing="YABOOT add kernel" yabootTest yaboot.1 add/y1.1 --copy-default --boot-filesystem=/ --add-kernel=/boot/new-kernel \ --title=newtitle yabootTest yaboot.1 add/y1.2 --add-kernel=/boot/new-kernel --boot-filesystem=/ --title=newtitle -echo "YABOOT empty label..." +testing="YABOOT empty label" yabootTest yaboot.3 add/y3.1 --add-kernel=/boot/new-kernel --boot-filesystem=/ --title=newtitle -echo "Z/IPL add kernel..." +testing="Z/IPL add kernel" ziplTest zipl.1 add/z1.1 --add-kernel=/boot/new-kernel.img --title test ziplTest zipl.1 add/z1.2 --add-kernel=/boot/new-kernel.img --title test --copy-default -echo "LILO long titles..." +testing="LILO long titles" liloTest lilo.1 longtitle/l1.1 --add-kernel=/boot/new-kernel.img \ --title="linux-longtitle" --copy-default --boot-filesystem=/boot liloTest lilo.1 longtitle/l1.2 --add-kernel=/boot/new-kernel.img \ @@ -280,11 +298,11 @@ liloTest lilo.7 longtitle/l7.1 --add-ker liloTest lilo.7 longtitle/l7.1 --add-kernel=/boot/new-kernel.img \ --title="linux-longtitle-fix" --copy-default --boot-filesystem=/boot -echo "ELILO long titles..." +testing="ELILO long titles" eliloTest lilo.7 longtitle/e7.1 --add-kernel=/boot/new-kernel.img \ --title="linux-longtitle-fix" --copy-default --boot-filesystem=/boot -echo "GRUB add multiboot..." +testing="GRUB add multiboot" grubTest grub.1 multiboot/g1.1 --add-multiboot=/boot/xen.gz \ --add-kernel=/boot/vmlinuz-2.6.10-1.1088_FC4 --boot-filesystem=/boot \ --initrd=/boot/initrd-2.6.10-1.1088_FC4.img --title foo \ @@ -308,7 +326,7 @@ grubTest grub.10 multiboot/g10.4 --add-k --initrd=/boot/initrd-2.6.10-1.1088_FC4.img --title foo \ --boot-filesystem=/boot -echo "GRUB remove multiboot..." +testing="GRUB remove multiboot" grubTest grub.10 multiboot/g10.5 --boot-filesystem=/boot \ --remove-kernel=/boot/vmlinuz-2.6.10-1.1076_FC4 grubTest grub.10 multiboot/g10.6 --boot-filesystem=/boot \ @@ -316,4 +334,8 @@ grubTest grub.10 multiboot/g10.7 --boot- grubTest grub.10 multiboot/g10.7 --boot-filesystem=/boot \ --remove-multiboot=/boot/xen.gz -exit $RESULT +printf "\n%d (%d%%) tests passed, %d (%d%%) tests failed\n" \ + $pass $(((100*pass)/(pass+fail))) \ + $fail $(((100*fail)/(pass+fail))) + +exit $(( !!fail ))
# HG changeset patch # User agriffis@cheo.zko.hp.com # Node ID 42e7d064ab2666bad84fc61f0465bee4f7c79d65 # Parent 8bbf845cad0dc1774c348f036d4eaa0365aef7e9 Add new generic functions This patch adds some generic functions to make extending grubby a little easier, and makes changes throughout the code to take advantage of them. - new function for duplicating a line (deep copy): dupLine - new functions for manipulating singleLine->element arrays: insertElement removeElement - new functions for matching keywords to types: getKeywordByType getTypeByKeyword - new functions for search an entry for lines matching a bitmask of types: getLineByType - new function for inserting a line to an entry from a template: addLineTmpl - simple debugging via dbgPrintf, which is normally compiled out Grubby builds with this patch and introduces no regressions. Signed-off-by: Aron Griffis <aron@hp.com> grubby.c | 452 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 287 insertions(+), 165 deletions(-) diff -r 8bbf845cad0d -r 42e7d064ab26 grubby/grubby.c --- a/grubby/grubby.c Thu Jun 29 12:21:58 2006 -0400 +++ b/grubby/grubby.c Thu Jun 29 16:10:13 2006 -0400 @@ -31,6 +31,14 @@ #include "block.h" +#define DEBUG 0 + +#if DEBUG +#define dbgPrintf(format, args...) fprintf(stderr, format , ## args) +#else +#define dbgPrintf(format, args...) +#endif + #define _(A) (A) #define CODE_SEG_SIZE 128 /* code segment checked by --bootloader-probe */ @@ -41,9 +49,23 @@ struct lineElement { char * indent; }; -enum lineType_e { LT_WHITESPACE, LT_TITLE, LT_KERNEL, LT_INITRD, LT_DEFAULT, - LT_UNKNOWN, LT_ROOT, LT_FALLBACK, LT_KERNELARGS, LT_BOOT, - LT_BOOTROOT, LT_LBA, LT_MBMODULE, LT_OTHER, LT_GENERIC }; +enum lineType_e { + LT_WHITESPACE = 1 << 0, + LT_TITLE = 1 << 1, + LT_KERNEL = 1 << 2, + LT_INITRD = 1 << 3, + LT_DEFAULT = 1 << 5, + LT_MBMODULE = 1 << 6, + LT_ROOT = 1 << 7, + LT_FALLBACK = 1 << 8, + LT_KERNELARGS = 1 << 9, + LT_BOOT = 1 << 10, + LT_BOOTROOT = 1 << 11, + LT_LBA = 1 << 12, + LT_OTHER = 1 << 13, + LT_GENERIC = 1 << 14, + LT_UNKNOWN = 1 << 15, +}; struct singleLine { char * indent; @@ -77,7 +99,7 @@ struct keywordTypes { char * key; enum lineType_e type; char nextChar; -} ; +}; struct configFileInfo { char * defaultConfig; @@ -258,19 +280,28 @@ struct grubConfig { struct configFileInfo * cfi; }; - struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index); struct singleEntry * findEntryByPath(struct grubConfig * cfg, const char * path, const char * prefix, int * index); static int readFile(int fd, char ** bufPtr); static void lineInit(struct singleLine * line); +struct singleLine * lineDup(struct singleLine * line); static void lineFree(struct singleLine * line); static int lineWrite(FILE * out, struct singleLine * line, struct configFileInfo * cfi); static int getNextLine(char ** bufPtr, struct singleLine * line, struct configFileInfo * cfi); static char * getRootSpecifier(char * str); +static void insertElement(struct singleLine * line, + const char * item, int insertHere); +static void removeElement(struct singleLine * line, int removeHere); +static struct keywordTypes * getKeywordByType(enum lineType_e type, + struct configFileInfo * cfi); +static enum lineType_e getTypeByKeyword(char * keyword, + struct configFileInfo * cfi); +static struct singleLine * getLineByType(enum lineType_e type, + struct singleLine * line); static char * sdupprintf(const char *format, ...) #ifdef __GNUC__ @@ -305,8 +336,40 @@ static char * sdupprintf(const char *for return buf; } +static struct keywordTypes * getKeywordByType(enum lineType_e type, + struct configFileInfo * cfi) { + struct keywordTypes * kw; + for (kw = cfi->keywords; kw->key; kw++) { + if (kw->type == type) + return kw; + } + return NULL; +} + +static enum lineType_e getTypeByKeyword(char * keyword, + struct configFileInfo * cfi) { + struct keywordTypes * kw; + for (kw = cfi->keywords; kw->key; kw++) { + if (!strcmp(keyword, kw->key)) + return kw->type; + } + return LT_UNKNOWN; +} + +static struct singleLine * getLineByType(enum lineType_e type, + struct singleLine * line) { + dbgPrintf("getLineByType(%d): ", type); + for (; line; line = line->next) { + dbgPrintf("%d:%s ", line->type, + line->numElements ? line->elements[0].item : "(empty)"); + if (line->type & type) break; + } + dbgPrintf(line ? "\n" : " (failed)\n"); + return line; +} + static int isBracketedTitle(struct singleLine * line) { - if ((*line->elements[0].item == ''['') && (line->numElements == 1)) { + if (line->numElements == 1 && *line->elements[0].item == ''['') { int len = strlen(line->elements[0].item); if (*(line->elements[0].item + len - 1) == '']'') { /* FIXME: this is a hack... */ @@ -318,19 +381,10 @@ static int isBracketedTitle(struct singl return 0; } -/* figure out if this is a entry separator */ static int isEntrySeparator(struct singleLine * line, struct configFileInfo * cfi) { - if (line->type == LT_WHITESPACE) - return 0; - if (line->type == cfi->entrySeparator) - return 1; - if (line->type == LT_OTHER) - return 1; - if (cfi->titleBracketed && isBracketedTitle(line)) { - return 1; - } - return 0; + return line->type == cfi->entrySeparator || line->type == LT_OTHER || + (cfi->titleBracketed && isBracketedTitle(line)); } /* extract the title from within brackets (for zipl) */ @@ -381,6 +435,25 @@ static void lineInit(struct singleLine * line->next = NULL; } +struct singleLine * lineDup(struct singleLine * line) { + int i; + struct singleLine * newLine = malloc(sizeof(*newLine)); + + newLine->indent = strdup(line->indent); + newLine->next = NULL; + newLine->type = line->type; + newLine->numElements = line->numElements; + newLine->elements = malloc(sizeof(*newLine->elements) * + newLine->numElements); + + for (i = 0; i < newLine->numElements; i++) { + newLine->elements[i].indent = strdup(line->elements[i].indent); + newLine->elements[i].item = strdup(line->elements[i].item); + } + + return newLine; +} + static void lineFree(struct singleLine * line) { int i; @@ -425,9 +498,7 @@ static int getNextLine(char ** bufPtr, s char * chptr; int elementsAlloced = 0; struct lineElement * element; - struct keywordTypes * keywords = cfi->keywords; int first = 1; - int i; lineFree(line); @@ -481,14 +552,8 @@ static int getNextLine(char ** bufPtr, s if (!line->numElements) line->type = LT_WHITESPACE; else { - for (i = 0; keywords[i].key; i++) - if (!strcmp(line->elements[0].item, keywords[i].key)) break; - - if (keywords[i].key) { - line->type = keywords[i].type; - } else { - line->type = LT_UNKNOWN; - + line->type = getTypeByKeyword(line->elements[0].item, cfi); + if (line->type == LT_UNKNOWN) { /* zipl does [title] instead of something reasonable like all * the other boot loaders. kind of ugly */ if (cfi->titleBracketed && isBracketedTitle(line)) { @@ -761,8 +826,7 @@ static void writeDefault(FILE * out, cha if (!entry) return; - line = entry->lines; - while (line && line->type != LT_TITLE) line = line->next; + line = getLineByType(LT_TITLE, entry->lines); if (line && line->numElements >= 2) fprintf(out, "%sdefault%s%s\n", indent, separator, @@ -913,12 +977,10 @@ int suitableImage(struct singleEntry * e char * dev; char * rootspec; - line = entry->lines; - while (line && line->type != LT_KERNEL) line = line->next; - - if (!line) return 0; if (skipRemoved && entry->skip) return 0; - if (line->numElements < 2) return 0; + + line = getLineByType(LT_KERNEL, entry->lines); + if (!line || line->numElements < 2) return 0; if (flags & GRUBBY_BADIMAGE_OKAY) return 1; @@ -926,8 +988,7 @@ int suitableImage(struct singleEntry * e strlen(line->elements[1].item) + 1); rootspec = getRootSpecifier(line->elements[1].item); sprintf(fullName, "%s%s", bootPrefix, - line->elements[1].item + ((rootspec != NULL) ? - strlen(rootspec) : 0)); + line->elements[1].item + (rootspec ? strlen(rootspec) : 0)); if (access(fullName, R_OK)) return 0; for (i = 2; i < line->numElements; i++) @@ -936,19 +997,15 @@ int suitableImage(struct singleEntry * e dev = line->elements[i].item + 5; } else { /* look for a lilo style LT_ROOT line */ - line = entry->lines; - while (line && line->type != LT_ROOT) line = line->next; + line = getLineByType(LT_ROOT, entry->lines); if (line && line->numElements >= 2) { dev = line->elements[1].item; } else { - int type; - /* didn''t succeed in finding a LT_ROOT, let''s try LT_KERNELARGS */ - line = entry->lines; - - type = ((entry->multiboot) ? LT_MBMODULE : LT_KERNELARGS); - - while (line && line->type != type) line = line->next; + /* didn''t succeed in finding a LT_ROOT, let''s try LT_KERNELARGS. + * grub+multiboot uses LT_MBMODULE for the args, so check that too. + */ + line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines); /* failed to find one */ if (!line) return 0; @@ -1019,10 +1076,7 @@ struct singleEntry * findEntryByPath(str entry = findEntryByIndex(config, indexVars[i]); if (!entry) return NULL; - line = entry->lines; - while (line && line->type != LT_KERNEL) - line = line->next; - + line = getLineByType(LT_KERNEL, entry->lines); if (!line) return NULL; if (index) *index = indexVars[i]; @@ -1064,47 +1118,35 @@ struct singleEntry * findEntryByPath(str kernel += 6; } - while ((entry = findEntryByIndex(config, i))) { - line = entry->lines; - while (line && line->type != checkType) line=line->next; - - - if (line && line->numElements >= 2 && !entry->skip) { - rootspec = getRootSpecifier(line->elements[1].item); - if (!strcmp(line->elements[1].item + - ((rootspec != NULL) ? strlen(rootspec) : 0), - kernel + strlen(prefix))) - break; - } - - /* have to check multiboot lines too */ - if (entry->multiboot) { - while (line && line->type != LT_MBMODULE) line = line->next; - if (line && line->numElements >= 2 && !entry->skip) { - rootspec = getRootSpecifier(line->elements[1].item); - if (!strcmp(line->elements[1].item + - ((rootspec != NULL) ? strlen(rootspec) : 0), - kernel + strlen(prefix))) - break; - } - } - - i++; + for (entry = findEntryByIndex(config, i); entry; entry = entry->next, i++) { + if (entry->skip) continue; + + dbgPrintf("findEntryByPath looking for %d %s in %p\n", checkType, kernel, entry); + + /* check all the lines matching checkType */ + for (line = entry->lines; line; line = line->next) { + line = getLineByType(entry->multiboot && checkType == LT_KERNEL ? + LT_KERNEL|LT_MBMODULE : checkType, line); + if (!line) break; /* not found in this entry */ + + if (line && line->numElements >= 2) { + rootspec = getRootSpecifier(line->elements[1].item); + if (!strcmp(line->elements[1].item + + ((rootspec != NULL) ? strlen(rootspec) : 0), + kernel + strlen(prefix))) + break; + } + } + + /* make sure this entry has a kernel identifier; this skips + * non-Linux boot entries (could find netbsd etc, though, which is + * unfortunate) + */ + if (line && getLineByType(LT_KERNEL, entry->lines)) + break; /* found ''im! */ } if (index) *index = i; - } - - if (!entry) return NULL; - - /* make sure this entry has a kernel identifier; this skips non-Linux - boot entries (could find netbsd etc, though, which is unfortunate) */ - line = entry->lines; - while (line && line->type != LT_KERNEL) line = line->next; - if (!line) { - if (!index) index = &i; - (*index)++; - return findEntryByPath(config, kernel, prefix, index); } return entry; @@ -1271,11 +1313,9 @@ void displayEntry(struct singleEntry * e char * root = NULL; int i; - line = entry->lines; - while (line && line->type != LT_KERNEL) line = line->next; - printf("index=%d\n", index); + line = getLineByType(LT_KERNEL, entry->lines); printf("kernel=%s\n", line->elements[1].item); if (line->numElements >= 3) { @@ -1293,9 +1333,7 @@ void displayEntry(struct singleEntry * e } printf("\"\n"); } else { - line = entry->lines; - while (line && line->type != LT_KERNELARGS) line=line->next; - + line = getLineByType(LT_KERNELARGS, entry->lines); if (line) { char * s; @@ -1319,9 +1357,7 @@ void displayEntry(struct singleEntry * e } if (!root) { - line = entry->lines; - while (line && line->type != LT_ROOT) line = line->next; - + line = getLineByType(LT_ROOT, entry->lines); if (line && line->numElements >= 2) root=line->elements[1].item; } @@ -1336,8 +1372,7 @@ void displayEntry(struct singleEntry * e printf("root=%s\n", s); } - line = entry->lines; - while (line && line->type != LT_INITRD) line = line->next; + line = getLineByType(LT_INITRD, entry->lines); if (line && line->numElements >= 2) { printf("initrd=%s", prefix); @@ -1421,14 +1456,12 @@ int displayInfo(struct grubConfig * conf if (config->cfi == &grubConfigType) { dumpSysconfigGrub(); } else { - line = config->theLines; - while (line && line->type != LT_BOOT) line = line->next; + line = getLineByType(LT_BOOT, config->theLines); if (line && line->numElements >= 1) { printf("boot=%s\n", line->elements[1].item); } - line = config->theLines; - while (line && line->type != LT_LBA) line = line->next; + line = getLineByType(LT_LBA, config->theLines); if (line) printf("lba\n"); } @@ -1443,77 +1476,100 @@ int displayInfo(struct grubConfig * conf return 0; } +struct singleLine * addLineTmpl(struct singleEntry * entry, + struct singleLine * tmplLine, + struct singleLine * prevLine, + const char * val) { + struct singleLine * newLine = lineDup(tmplLine); + + if (val) { + /* override the inherited value with our own. + * This is a little weak because it only applies to elements[1] + */ + if (newLine->numElements > 1) + removeElement(newLine, 1); + insertElement(newLine, val, 1); + + /* but try to keep the rootspec from the template... sigh */ + if (tmplLine->type & (LT_KERNEL|LT_MBMODULE|LT_INITRD)) { + char * rootspec = getRootSpecifier(tmplLine->elements[1].item); + if (rootspec != NULL) { + free(newLine->elements[1].item); + newLine->elements[1].item = + sdupprintf("%s%s", rootspec, val); + } + } + } + + dbgPrintf("addLineTmpl(%s)\n", newLine->numElements ? + newLine->elements[0].item : ""); + + if (!entry->lines) { + /* first one on the list */ + entry->lines = newLine; + } else if (prevLine) { + /* add after prevLine */ + newLine->next = prevLine->next; + prevLine->next = newLine; + } + + return newLine; +} + /* val may be NULL */ struct singleLine * addLine(struct singleEntry * entry, struct configFileInfo * cfi, - enum lineType_e type, const char * defaultIndent, - char * val) { + enum lineType_e type, char * defaultIndent, + const char * val) { struct singleLine * line, * prev; - int i; - - for (i = 0; cfi->keywords[i].key; i++) - if (cfi->keywords[i].type == type) break; - if (type != LT_TITLE || !cfi->titleBracketed) - if (!cfi->keywords[i].key) abort(); + struct keywordTypes * kw; + struct singleLine tmpl; + + /* NB: This function shouldn''t allocate items on the heap, rather on the + * stack since it calls addLineTmpl which will make copies. + */ + + if (type == LT_TITLE && cfi->titleBracketed) { + /* we''re doing a bracketed title (zipl) */ + tmpl.type = type; + tmpl.numElements = 1; + tmpl.elements = alloca(sizeof(*tmpl.elements)); + tmpl.elements[0].item = alloca(strlen(val)+3); + sprintf(tmpl.elements[0].item, "[%s]", val); + tmpl.elements[0].indent = ""; + val = NULL; + } else { + kw = getKeywordByType(type, cfi); + if (!kw) abort(); + tmpl.type = type; + tmpl.numElements = val ? 2 : 1; + tmpl.elements = alloca(sizeof(*tmpl.elements) * tmpl.numElements); + tmpl.elements[0].item = kw->key; + tmpl.elements[0].indent = alloca(2); + sprintf(tmpl.elements[0].indent, "%c", kw->nextChar); + if (val) { + tmpl.elements[1].item = (char *)val; + tmpl.elements[1].indent = ""; + } + } /* The last non-empty line gives us the indention to us and the line to insert after. Note that comments are considered empty lines, which may not be ideal? If there are no lines or we are looking at the first line, we use defaultIndent (the first line is normally indented differently from the rest) */ - if (entry->lines) { - line = entry->lines; - prev = NULL; - while (line) { - if (line->numElements) prev = line; - line = line->next; - } - if (!prev) { - /* just use the last line */ - prev = entry->lines; - while (prev->next) prev = prev->next; - } - - line = prev->next; - prev->next = malloc(sizeof(*line)); - prev->next->next = line; - line = prev->next; - - if (prev == entry->lines) - line->indent = strdup(defaultIndent); - else - line->indent = strdup(prev->indent); - } else { - line = malloc(sizeof(*line)); - line->indent = strdup(defaultIndent); - line->next = NULL; - } - - if (type != LT_TITLE || !cfi->titleBracketed) { - line->type = type; - line->numElements = val ? 2 : 1; - line->elements = malloc(sizeof(*line->elements) * line->numElements); - line->elements[0].item = strdup(cfi->keywords[i].key); - line->elements[0].indent = malloc(2); - line->elements[0].indent[0] = cfi->keywords[i].nextChar; - line->elements[0].indent[1] = ''\0''; - - if (val) { - line->elements[1].item = val; - line->elements[1].indent = strdup(""); - } - } else { - /* we''re doing the title of a bracketed title (zipl) */ - line->type = type; - line->numElements = 1; - line->elements = malloc(sizeof(*line->elements) * line->numElements); - - line->elements[0].item = malloc(strlen(val) + 3); - sprintf(line->elements[0].item, "[%s]", val); - line->elements[0].indent = strdup(""); - } - - return line; + for (line = entry->lines, prev = NULL; line; line = line->next) { + if (line->numElements) prev = line; + /* fall back on the last line if prev isn''t otherwise set */ + if (!line->next && !prev) prev = line; + } + + if (prev == entry->lines) + tmpl.indent = defaultIndent ?: ""; + else + tmpl.indent = prev->indent; + + return addLineTmpl(entry, &tmpl, prev, val); } void removeLine(struct singleEntry * entry, struct singleLine * line) { @@ -1536,6 +1592,73 @@ void removeLine(struct singleEntry * ent } free(line); +} + +static void insertElement(struct singleLine * line, + const char * item, int insertHere) { + + /* sanity check */ + if (insertHere > line->numElements) { + dbgPrintf("insertElement() adjusting insertHere from %d to %d\n", + insertHere, line->numElements); + insertHere = line->numElements; + } + + line->elements = realloc(line->elements, (line->numElements + 1) * + sizeof(*line->elements)); + memmove(&line->elements[insertHere+1], + &line->elements[insertHere], + (line->numElements - insertHere) * + sizeof(*line->elements)); + line->elements[insertHere].item = strdup(item); + + if (insertHere > 0 && line->elements[insertHere-1].indent[0] == ''\0'') { + /* move the end-of-line forward */ + line->elements[insertHere].indent = + line->elements[insertHere-1].indent; + line->elements[insertHere-1].indent = strdup(" "); + } else { + /* technically this should honor nextChar from keywordTypes + * when insertHere == 0, but oh well + */ + line->elements[insertHere].indent = + strdup(insertHere == line->numElements ? "" : " "); + } + + line->numElements++; + + dbgPrintf("insertElement(%s, ''%s%s'', %d)\n", + line->elements[0].item, + line->elements[insertHere].item, + line->elements[insertHere].indent, + insertHere); +} + +static void removeElement(struct singleLine * line, int removeHere) { + int i; + + /* sanity check */ + if (removeHere >= line->numElements) return; + + dbgPrintf("removeElement(%s, %d:%s)\n", line->elements[0].item, + removeHere, line->elements[removeHere].item); + + free(line->elements[removeHere].item); + + if (removeHere > 1) { + /* previous argument gets this argument''s post-indentation */ + free(line->elements[removeHere-1].indent); + line->elements[removeHere-1].indent + line->elements[removeHere].indent; + } else { + free(line->elements[removeHere].indent); + } + + /* now collapse the array, but don''t bother to realloc smaller */ + for (i = removeHere; i < line->numElements - 1; i++) + line->elements[i] = line->elements[i + 1]; + + line->numElements--; } int argMatch(const char * one, const char * two) { @@ -2546,8 +2669,7 @@ int main(int argc, const char ** argv) { if (!entry) return 0; if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; - line = entry->lines; - while (line && line->type != LT_KERNEL) line = line->next; + line = getLineByType(LT_KERNEL, entry->lines); if (!line) return 0; rootspec = getRootSpecifier(line->elements[1].item);
# HG changeset patch # User agriffis@cheo.zko.hp.com # Node ID ecdec03697eab8a622e46755d0330a05694f14f5 # Parent 42e7d064ab2666bad84fc61f0465bee4f7c79d65 Add support for LT_HYPER This patch adds support for the LT_HYPER line type. Whereas grub uses kernel=hypervisor module=kernel module=initrd, elilo uses vmm=hypervisor image=kernel initrd=initrd. Adding LT_HYPER support, and extending it backward to grub, makes dealing with this a lot easier. configFileInfo->mbHyperFirst is added to differentiate between grub wanting the hypervisor listed first, and elilo wanting the kernel listed first (image= is the entry separator so it''s very important) configFileInfo->mbInitRdIsModule is added to handle grub wanting the initrd listed as a module when multibooting The logic in addNewKernel is considerably rewritten (and cleaned up!) to be more generic and handle elilo alongside grub. Additionally one memcpy is corrected to memmove, since it was unsafely copying overlapping regions. Grubby builds with this patch and no new regressions are reported by the test suite. Signed-off-by: Aron Griffis <aron@hp.com> grubby.c | 531 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 294 insertions(+), 237 deletions(-) diff -r 42e7d064ab26 -r ecdec03697ea grubby/grubby.c --- a/grubby/grubby.c Thu Jun 29 16:10:13 2006 -0400 +++ b/grubby/grubby.c Thu Jun 29 16:33:24 2006 -0400 @@ -54,6 +54,7 @@ enum lineType_e { LT_TITLE = 1 << 1, LT_KERNEL = 1 << 2, LT_INITRD = 1 << 3, + LT_HYPER = 1 << 4, LT_DEFAULT = 1 << 5, LT_MBMODULE = 1 << 6, LT_ROOT = 1 << 7, @@ -86,11 +87,12 @@ struct singleEntry { #define GRUB_CONFIG_NO_DEFAULT (1 << 0) /* don''t write out default=0 */ -#define KERNEL_KERNEL (1 << 0) -#define KERNEL_INITRD (1 << 2) -#define KERNEL_TITLE (1 << 3) -#define KERNEL_ARGS (1 << 4) -#define KERNEL_MB (1 << 5) +/* These defines are (only) used in addNewKernel() */ +#define NEED_KERNEL (1 << 0) +#define NEED_INITRD (1 << 1) +#define NEED_TITLE (1 << 2) +#define NEED_ARGS (1 << 3) +#define NEED_MB (1 << 4) #define MAIN_DEFAULT (1 << 0) #define DEFAULT_SAVED -2 @@ -111,6 +113,8 @@ struct configFileInfo { int argsInQuotes; int maxTitleLength; int titleBracketed; + int mbHyperFirst; + int mbInitRdIsModule; }; struct keywordTypes grubKeywords[] = { @@ -121,6 +125,7 @@ struct keywordTypes grubKeywords[] = { { "kernel", LT_KERNEL, '' '' }, { "initrd", LT_INITRD, '' '' }, { "module", LT_MBMODULE, '' '' }, + { "kernel", LT_HYPER, '' '' }, { NULL, 0, 0 }, }; @@ -134,6 +139,8 @@ struct configFileInfo grubConfigType = { 0, /* argsInQuotes */ 0, /* maxTitleLength */ 0, /* titleBracketed */ + 1, /* mbHyperFirst */ + 1, /* mbInitRdIsModule */ }; struct keywordTypes yabootKeywords[] = { @@ -187,6 +194,17 @@ struct keywordTypes liloKeywords[] = { { NULL, 0, 0 }, }; +struct keywordTypes eliloKeywords[] = { + { "label", LT_TITLE, ''='' }, + { "root", LT_ROOT, ''='' }, + { "default", LT_DEFAULT, ''='' }, + { "image", LT_KERNEL, ''='' }, + { "initrd", LT_INITRD, ''='' }, + { "append", LT_KERNELARGS, ''='' }, + { "vmm", LT_HYPER, ''='' }, + { NULL, 0, 0 }, +}; + struct keywordTypes siloKeywords[] = { { "label", LT_TITLE, ''='' }, { "root", LT_ROOT, ''='' }, @@ -210,7 +228,7 @@ struct keywordTypes ziplKeywords[] = { struct configFileInfo eliloConfigType = { "/boot/efi/EFI/redhat/elilo.conf", /* defaultConfig */ - liloKeywords, /* keywords */ + eliloKeywords, /* keywords */ 0, /* defaultIsIndex */ 0, /* defaultSupportSaved */ LT_KERNEL, /* entrySeparator */ @@ -218,6 +236,8 @@ struct configFileInfo eliloConfigType = 1, /* argsInQuotes */ 0, /* maxTitleLength */ 0, /* titleBracketed */ + 0, /* mbHyperFirst */ + 0, /* mbInitRdIsModule */ }; struct configFileInfo liloConfigType = { @@ -230,6 +250,8 @@ struct configFileInfo liloConfigType = { 1, /* argsInQuotes */ 15, /* maxTitleLength */ 0, /* titleBracketed */ + 0, /* mbHyperFirst */ + 0, /* mbInitRdIsModule */ }; struct configFileInfo yabootConfigType = { @@ -242,6 +264,8 @@ struct configFileInfo yabootConfigType 1, /* argsInQuotes */ 15, /* maxTitleLength */ 0, /* titleBracketed */ + 0, /* mbHyperFirst */ + 0, /* mbInitRdIsModule */ }; struct configFileInfo siloConfigType = { @@ -254,6 +278,8 @@ struct configFileInfo siloConfigType = { 1, /* argsInQuotes */ 15, /* maxTitleLength */ 0, /* titleBracketed */ + 0, /* mbHyperFirst */ + 0, /* mbInitRdIsModule */ }; struct configFileInfo ziplConfigType = { @@ -266,6 +292,8 @@ struct configFileInfo ziplConfigType = { 1, /* argsInQuotes */ 15, /* maxTitleLength */ 1, /* titleBracketed */ + 0, /* mbHyperFirst */ + 0, /* mbInitRdIsModule */ }; struct grubConfig { @@ -671,11 +699,39 @@ static struct grubConfig * readConfig(co if (line->type == LT_DEFAULT && line->numElements == 2) { cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; defaultLine = line; + + } else if (line->type == LT_KERNEL) { + /* if by some freak chance this is multiboot and the "module" + * lines came earlier in the template, make sure to use LT_HYPER + * instead of LT_KERNEL now + */ + if (entry->multiboot) + line->type = LT_HYPER; + } else if (line->type == LT_MBMODULE) { + /* go back and fix the LT_KERNEL line to indicate LT_HYPER + * instead, now that we know this is a multiboot entry. + * This only applies to grub, but that''s the only place we + * should find LT_MBMODULE lines anyway. + */ + struct singleLine * l; + for (l = entry->lines; l; l = l->next) { + if (l->type == LT_HYPER) + break; + else if (l->type == LT_KERNEL) { + l->type = LT_HYPER; + break; + } + } entry->multiboot = 1; + + } else if (line->type == LT_HYPER) { + entry->multiboot = 1; + } else if (line->type == LT_FALLBACK && line->numElements == 2) { cfg->fallbackImage = strtol(line->elements[1].item, &end, 10); if (*end) cfg->fallbackImage = -1; + } else if (line->type == LT_TITLE && line->numElements > 1) { /* make the title a single argument (undoing our parsing) */ len = 0; @@ -700,6 +756,7 @@ static struct grubConfig * readConfig(co line->elements[line->numElements - 1].indent; line->elements[1].item = buf; line->numElements = 2; + } else if (line->type == LT_KERNELARGS && cfi->argsInQuotes) { /* Strip off any " which may be present; they''ll be put back on write. This is one of the few (the only?) places that grubby @@ -709,15 +766,14 @@ static struct grubConfig * readConfig(co int last, len; if (*line->elements[1].item == ''"'') - memcpy(line->elements[1].item, line->elements[1].item + 1, - strlen(line->elements[1].item + 1) + 1); + memmove(line->elements[1].item, line->elements[1].item + 1, + strlen(line->elements[1].item + 1) + 1); last = line->numElements - 1; len = strlen(line->elements[last].item) - 1; if (line->elements[last].item[len] == ''"'') line->elements[last].item[len] = ''\0''; } - } /* If we find a generic config option which should live at the @@ -737,6 +793,7 @@ static struct grubConfig * readConfig(co movedLine = 1; continue; /* without setting ''last'' */ } + /* If a second line of whitespace happens after a generic option which was moved, drop it. */ if (movedLine && line->type == LT_WHITESPACE && last->type == LT_WHITESPACE) { @@ -752,12 +809,13 @@ static struct grubConfig * readConfig(co entry->lines = line; else last->next = line; + dbgPrintf("readConfig added %d to %p\n", line->type, entry); } else { if (!cfg->theLines) cfg->theLines = line; - else { + else last->next = line; - } + dbgPrintf("readConfig added %d to cfg\n", line->type); } last = line; @@ -979,7 +1037,7 @@ int suitableImage(struct singleEntry * e if (skipRemoved && entry->skip) return 0; - line = getLineByType(LT_KERNEL, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); if (!line || line->numElements < 2) return 0; if (flags & GRUBBY_BADIMAGE_OKAY) return 1; @@ -1076,7 +1134,7 @@ struct singleEntry * findEntryByPath(str entry = findEntryByIndex(config, indexVars[i]); if (!entry) return NULL; - line = getLineByType(LT_KERNEL, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); if (!line) return NULL; if (index) *index = indexVars[i]; @@ -1126,7 +1184,8 @@ struct singleEntry * findEntryByPath(str /* check all the lines matching checkType */ for (line = entry->lines; line; line = line->next) { line = getLineByType(entry->multiboot && checkType == LT_KERNEL ? - LT_KERNEL|LT_MBMODULE : checkType, line); + LT_KERNEL|LT_MBMODULE|LT_HYPER : + checkType, line); if (!line) break; /* not found in this entry */ if (line && line->numElements >= 2) { @@ -1142,7 +1201,7 @@ struct singleEntry * findEntryByPath(str * non-Linux boot entries (could find netbsd etc, though, which is * unfortunate) */ - if (line && getLineByType(LT_KERNEL, entry->lines)) + if (line && getLineByType(LT_KERNEL|LT_HYPER, entry->lines)) break; /* found ''im! */ } @@ -1315,7 +1374,7 @@ void displayEntry(struct singleEntry * e printf("index=%d\n", index); - line = getLineByType(LT_KERNEL, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); printf("kernel=%s\n", line->elements[1].item); if (line->numElements >= 3) { @@ -1491,7 +1550,7 @@ struct singleLine * addLineTmpl(struct s insertElement(newLine, val, 1); /* but try to keep the rootspec from the template... sigh */ - if (tmplLine->type & (LT_KERNEL|LT_MBMODULE|LT_INITRD)) { + if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD)) { char * rootspec = getRootSpecifier(tmplLine->elements[1].item); if (rootspec != NULL) { free(newLine->elements[1].item); @@ -1737,8 +1796,7 @@ int updateActualImage(struct grubConfig while ((entry = findEntryByPath(cfg, image, prefix, &index))) { index++; - line = entry->lines; - while (line && line->type != LT_KERNEL) line = line->next; + line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); if (!line) continue; firstElement = 2; @@ -2108,13 +2166,9 @@ int addNewKernel(struct grubConfig * con char * newKernelArgs, char * newKernelInitrd, char * newMBKernel, char * newMBKernelArgs) { struct singleEntry * new; - struct singleLine * newLine = NULL, * tmplLine = NULL, * lastLine = NULL; + struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL; int needs; - char * indent = NULL; - char * rootspec = NULL; char * chptr; - int i; - enum lineType_e type; if (!newKernelPath) return 0; @@ -2144,236 +2198,239 @@ int addNewKernel(struct grubConfig * con config->entries = new; /* copy/update from the template */ - needs = KERNEL_KERNEL | KERNEL_INITRD | KERNEL_TITLE; + needs = NEED_KERNEL | NEED_TITLE; + if (newKernelInitrd) + needs |= NEED_INITRD; if (newMBKernel) { - needs |= KERNEL_MB; + needs |= NEED_MB; new->multiboot = 1; } if (template) { - for (tmplLine = template->lines; tmplLine; tmplLine = tmplLine->next) { - /* remember the indention level; we may need it for new lines */ - if (tmplLine->numElements) - indent = tmplLine->indent; + for (masterLine = template->lines; + masterLine && (tmplLine = lineDup(masterLine)); + lineFree(tmplLine), masterLine = masterLine->next) + { + dbgPrintf("addNewKernel processing %d\n", tmplLine->type); /* skip comments */ chptr = tmplLine->indent; while (*chptr && isspace(*chptr)) chptr++; if (*chptr == ''#'') continue; - /* we don''t need an initrd here */ - if (tmplLine->type == LT_INITRD && !newKernelInitrd) continue; - - if (tmplLine->type == LT_KERNEL && - !template->multiboot && (needs & KERNEL_MB)) { - struct singleLine *l; - needs &= ~ KERNEL_MB; - - l = addLine(new, config->cfi, LT_KERNEL, - config->secondaryIndent, - newMBKernel + strlen(prefix)); - - tmplLine = lastLine; - if (!new->lines) { - new->lines = l; - } else { - newLine->next = l; - newLine = l; - } - continue; - } else if (tmplLine->type == LT_KERNEL && - template->multiboot && !new->multiboot) { - continue; /* don''t need multiboot kernel here */ - } - - if (!new->lines) { - newLine = malloc(sizeof(*newLine)); - new->lines = newLine; + if (tmplLine->type == LT_KERNEL && + tmplLine->numElements >= 2) { + if (!template->multiboot && (needs & NEED_MB)) { + /* it''s not a multiboot template and this is the kernel + * line. Try to be intelligent about inserting the + * hypervisor at the same time. + */ + if (config->cfi->mbHyperFirst) { + /* insert the hypervisor first */ + newLine = addLine(new, config->cfi, LT_HYPER, + tmplLine->indent, + newMBKernel + strlen(prefix)); + /* set up for adding the kernel line */ + free(tmplLine->indent); + tmplLine->indent = strdup(config->secondaryIndent); + needs &= ~NEED_MB; + } + if (needs & NEED_KERNEL) { + /* use addLineTmpl to preserve line elements, + * otherwise we could just call addLine. Unfortunately + * this means making some changes to the template + * such as the indent change above and the type + * change below. + */ + struct keywordTypes * mbm_kw = + getKeywordByType(LT_MBMODULE, config->cfi); + if (mbm_kw) { + tmplLine->type = LT_MBMODULE; + free(tmplLine->elements[0].item); + tmplLine->elements[0].item = strdup(mbm_kw->key); + } + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelPath + strlen(prefix)); + needs &= ~NEED_KERNEL; + } + if (needs & NEED_MB) { /* !mbHyperFirst */ + newLine = addLine(new, config->cfi, LT_HYPER, + config->secondaryIndent, + newMBKernel + strlen(prefix)); + needs &= ~NEED_MB; + } + } else if (needs & NEED_KERNEL) { + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelPath + strlen(prefix)); + needs &= ~NEED_KERNEL; + } + + } else if (tmplLine->type == LT_HYPER && + tmplLine->numElements >= 2) { + if (needs & NEED_MB) { + newLine = addLineTmpl(new, tmplLine, newLine, + newMBKernel + strlen(prefix)); + needs &= ~NEED_MB; + } + + } else if (tmplLine->type == LT_MBMODULE && + tmplLine->numElements >= 2) { + if (new->multiboot) { + if (needs & NEED_KERNEL) { + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelPath + + strlen(prefix)); + needs &= ~NEED_KERNEL; + } else if (config->cfi->mbInitRdIsModule && + (needs & NEED_INITRD)) { + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelInitrd + + strlen(prefix)); + needs &= ~NEED_INITRD; + } + } else if (needs & NEED_KERNEL) { + /* template is multi but new is not, + * insert the kernel in the first module slot + */ + tmplLine->type = LT_KERNEL; + free(tmplLine->elements[0].item); + tmplLine->elements[0].item = + strdup(getKeywordByType(LT_KERNEL, config->cfi)->key); + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelPath + strlen(prefix)); + needs &= ~NEED_KERNEL; + } else if (needs & NEED_INITRD) { + /* template is multi but new is not, + * insert the initrd in the second module slot + */ + tmplLine->type = LT_INITRD; + free(tmplLine->elements[0].item); + tmplLine->elements[0].item = + strdup(getKeywordByType(LT_INITRD, config->cfi)->key); + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelInitrd + strlen(prefix)); + needs &= ~NEED_INITRD; + } + + } else if (tmplLine->type == LT_INITRD && + tmplLine->numElements >= 2) { + if (needs & NEED_INITRD && + new->multiboot && !template->multiboot && + config->cfi->mbInitRdIsModule) { + /* make sure we don''t insert the module initrd + * before the module kernel... if we don''t do it here, + * it will be inserted following the template. + */ + if (!needs & NEED_KERNEL) { + newLine = addLine(new, config->cfi, LT_MBMODULE, + config->secondaryIndent, + newKernelInitrd + strlen(prefix)); + needs &= ~NEED_INITRD; + } + } else if (needs & NEED_INITRD) { + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelInitrd + strlen(prefix)); + needs &= ~NEED_INITRD; + } + + } else if (tmplLine->type == LT_TITLE && + (needs & NEED_TITLE)) { + if (tmplLine->numElements >= 2) { + newLine = addLineTmpl(new, tmplLine, newLine, + newKernelTitle); + needs &= ~NEED_TITLE; + } else if (tmplLine->numElements == 1 && + config->cfi->titleBracketed) { + /* addLineTmpl doesn''t handle titleBracketed */ + newLine = addLine(new, config->cfi, LT_TITLE, + tmplLine->indent, newKernelTitle); + needs &= ~NEED_TITLE; + } + } else { - newLine->next = malloc(sizeof(*newLine)); - newLine = newLine->next; + /* pass through other lines from the template */ + newLine = addLineTmpl(new, tmplLine, newLine, NULL); } - - - newLine->indent = strdup(tmplLine->indent); - newLine->next = NULL; - newLine->type = tmplLine->type; - newLine->numElements = tmplLine->numElements; - newLine->elements = malloc(sizeof(*newLine->elements) * - newLine->numElements); - for (i = 0; i < newLine->numElements; i++) { - newLine->elements[i].item = strdup(tmplLine->elements[i].item); - newLine->elements[i].indent = - strdup(tmplLine->elements[i].indent); - } - - lastLine = tmplLine; - if (tmplLine->type == LT_KERNEL && tmplLine->numElements >= 2) { - char * repl; - if (!template->multiboot) { - needs &= ~KERNEL_KERNEL; - repl = newKernelPath; - } else { - needs &= ~KERNEL_MB; - repl = newMBKernel; - } - if (new->multiboot && !template->multiboot) { - free(newLine->elements[0].item); - newLine->elements[0].item = strdup("module"); - newLine->type = LT_MBMODULE; - } - free(newLine->elements[1].item); - rootspec = getRootSpecifier(tmplLine->elements[1].item); - if (rootspec != NULL) { - newLine->elements[1].item = sdupprintf("%s%s", - rootspec, - repl + - strlen(prefix)); - } else { - newLine->elements[1].item = strdup(repl + - strlen(prefix)); - } - } else if (tmplLine->type == LT_MBMODULE && - tmplLine->numElements >= 2 && (needs & KERNEL_KERNEL)) { - needs &= ~KERNEL_KERNEL; - if (!new->multiboot && template->multiboot) { - free(newLine->elements[0].item); - newLine->elements[0].item = strdup("kernel"); - newLine->type = LT_KERNEL; - } - free(newLine->elements[1].item); - rootspec = getRootSpecifier(tmplLine->elements[1].item); - if (rootspec != NULL) { - newLine->elements[1].item = sdupprintf("%s%s", - rootspec, - newKernelPath + - strlen(prefix)); - } else { - newLine->elements[1].item = strdup(newKernelPath + - strlen(prefix)); - } - } else if (tmplLine->type == LT_INITRD && - tmplLine->numElements >= 2) { - needs &= ~KERNEL_INITRD; - free(newLine->elements[1].item); - if (new->multiboot && !template->multiboot) { - free(newLine->elements[0].item); - newLine->elements[0].item = strdup("module"); - newLine->type = LT_MBMODULE; - } - rootspec = getRootSpecifier(tmplLine->elements[1].item); - if (rootspec != NULL) { - newLine->elements[1].item = sdupprintf("%s%s", - rootspec, - newKernelInitrd + - strlen(prefix)); - } else { - newLine->elements[1].item = strdup(newKernelInitrd + - strlen(prefix)); - } - } else if (tmplLine->type == LT_MBMODULE && - tmplLine->numElements >= 2 && (needs & KERNEL_INITRD)) { - needs &= ~KERNEL_INITRD; - if (!new->multiboot && template->multiboot) { - free(newLine->elements[0].item); - newLine->elements[0].item = strdup("initrd"); - newLine->type = LT_INITRD; - } - free(newLine->elements[1].item); - rootspec = getRootSpecifier(tmplLine->elements[1].item); - if (rootspec != NULL) { - newLine->elements[1].item = sdupprintf("%s%s", - rootspec, - newKernelInitrd + - strlen(prefix)); - } else { - newLine->elements[1].item = strdup(newKernelInitrd + - strlen(prefix)); - } - } else if (tmplLine->type == LT_TITLE && - tmplLine->numElements >= 2) { - needs &= ~KERNEL_TITLE; - - for (i = 1; i < newLine->numElements; i++) { - free(newLine->elements[i].item); - free(newLine->elements[i].indent); + } + + } else { + /* don''t have a template, so start the entry with the + * appropriate starting line + */ + switch (config->cfi->entrySeparator) { + case LT_KERNEL: + if (new->multiboot && config->cfi->mbHyperFirst) { + /* fall through to LT_HYPER */ + } else { + newLine = addLine(new, config->cfi, LT_KERNEL, + config->primaryIndent, + newKernelPath + strlen(prefix)); + needs &= ~NEED_KERNEL; + break; } - newLine->elements[1].item = strdup(newKernelTitle); - newLine->elements[1].indent = strdup(""); - newLine->numElements = 2; - } else if (tmplLine->type == LT_TITLE && - config->cfi->titleBracketed && - tmplLine->numElements == 1) { - needs &= ~KERNEL_TITLE; - free(newLine->elements[0].item); - free(newLine->elements[0].indent); - newLine->elements = malloc(sizeof(*newLine->elements) * - newLine->numElements); - - newLine->elements[0].item = malloc(strlen(newKernelTitle) + 3); - sprintf(newLine->elements[0].item, "[%s]", newKernelTitle); - newLine->elements[0].indent = strdup(""); - newLine->numElements = 1; - } - } - } else { - for (i = 0; config->cfi->keywords[i].key; i++) { - if ((config->cfi->keywords[i].type == config->cfi->entrySeparator) || (config->cfi->keywords[i].type == LT_OTHER)) + case LT_HYPER: + newLine = addLine(new, config->cfi, LT_HYPER, + config->primaryIndent, + newMBKernel + strlen(prefix)); + needs &= ~NEED_MB; break; - } - - switch (config->cfi->keywords[i].type) { - case LT_KERNEL: needs &= ~KERNEL_KERNEL, - chptr = newKernelPath + strlen(prefix); - type = LT_KERNEL; break; - case LT_TITLE: needs &= ~KERNEL_TITLE, chptr = newKernelTitle; - type = LT_TITLE; break; - default: - /* zipl strikes again */ - if (config->cfi->titleBracketed) { - needs &= ~KERNEL_TITLE; - chptr = newKernelTitle; - type = LT_TITLE; - break; - } else { - abort(); - } - } - - newLine = addLine(new, config->cfi, type, config->primaryIndent, chptr); - new->lines = newLine; + + case LT_TITLE: + newLine = addLine(new, config->cfi, LT_TITLE, + config->primaryIndent, newKernelTitle); + needs &= ~NEED_TITLE; + break; + + default: + abort(); + } } - if (new->multiboot) { - if (needs & KERNEL_MB) - newLine = addLine(new, config->cfi, LT_KERNEL, - config->secondaryIndent, - newMBKernel + strlen(prefix)); - if (needs & KERNEL_KERNEL) - newLine = addLine(new, config->cfi, LT_MBMODULE, - config->secondaryIndent, - newKernelPath + strlen(prefix)); - /* don''t need to check for title as it''s guaranteed to have been - * done as we only do multiboot with grub which uses title as - * a separator */ - if (needs & KERNEL_INITRD && newKernelInitrd) - newLine = addLine(new, config->cfi, LT_MBMODULE, - config->secondaryIndent, - newKernelInitrd + strlen(prefix)); - } else { - if (needs & KERNEL_KERNEL) - newLine = addLine(new, config->cfi, LT_KERNEL, - config->secondaryIndent, - newKernelPath + strlen(prefix)); - if (needs & KERNEL_TITLE) - newLine = addLine(new, config->cfi, LT_TITLE, - config->secondaryIndent, - newKernelTitle); - if (needs & KERNEL_INITRD && newKernelInitrd) - newLine = addLine(new, config->cfi, LT_INITRD, - config->secondaryIndent, - newKernelInitrd + strlen(prefix)); + /* add the remainder of the lines, i.e. those that either + * weren''t present in the template, or in the case of no template, + * all the lines following the entrySeparator. + */ + if (needs & NEED_TITLE) { + newLine = addLine(new, config->cfi, LT_TITLE, + config->secondaryIndent, + newKernelTitle); + needs &= ~NEED_TITLE; + } + if ((needs & NEED_MB) && config->cfi->mbHyperFirst) { + newLine = addLine(new, config->cfi, LT_HYPER, + config->secondaryIndent, + newMBKernel + strlen(prefix)); + needs &= ~NEED_MB; + } + if (needs & NEED_KERNEL) { + newLine = addLine(new, config->cfi, + (new->multiboot && getKeywordByType(LT_MBMODULE, + config->cfi)) ? + LT_MBMODULE : LT_KERNEL, + config->secondaryIndent, + newKernelPath + strlen(prefix)); + needs &= ~NEED_KERNEL; + } + if (needs & NEED_MB) { + newLine = addLine(new, config->cfi, LT_HYPER, + config->secondaryIndent, + newMBKernel + strlen(prefix)); + needs &= ~NEED_MB; + } + if (needs & NEED_INITRD) { + newLine = addLine(new, config->cfi, + (new->multiboot && getKeywordByType(LT_MBMODULE, + config->cfi)) ? + LT_MBMODULE : LT_INITRD, + config->secondaryIndent, + newKernelInitrd + strlen(prefix)); + needs &= ~NEED_INITRD; + } + + if (needs) { + printf(_("grubby: needs=%d, aborting\n"), needs); + abort(); } if (updateImage(config, "0", prefix, newKernelArgs, NULL, @@ -2669,7 +2726,7 @@ int main(int argc, const char ** argv) { if (!entry) return 0; if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; - line = getLineByType(LT_KERNEL, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); if (!line) return 0; rootspec = getRootSpecifier(line->elements[1].item);
Aron Griffis
2006-Jun-29 21:42 UTC
[Fedora-xen] [PATCH 4 of 6] Modify updateActualImage to handle elilo-style args
# HG changeset patch # User agriffis@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@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); } }
Aron Griffis
2006-Jun-29 21:42 UTC
[Fedora-xen] [PATCH 5 of 6] Add test suite cases for elilo multiboot
# HG changeset patch # User agriffis@cheo.zko.hp.com # Node ID c21b0cf582a12df3f29601fca13f9ac82cf0ff06 # Parent bbebf7a97ae1e13bb2b3bce3dcc999a7de53aa98 Add test suite cases for elilo multiboot Additionally remove trailing whitespace from grubby/test/results/updargs/g3.7 since the recent grubby changes allow it to do a better job handling whitespace. Signed-off-by: Aron Griffis <aron@hp.com> grubby/test/elilo.1 | 25 +++++++++++++++++++++++++ grubby/test/elilo.2 | 30 ++++++++++++++++++++++++++++++ grubby/test/results/multiboot/e1.1 | 30 ++++++++++++++++++++++++++++++ grubby/test/results/multiboot/e1.2 | 32 ++++++++++++++++++++++++++++++++ grubby/test/results/multiboot/e2.1 | 26 ++++++++++++++++++++++++++ grubby/test/results/multiboot/e2.2 | 25 +++++++++++++++++++++++++ grubby/test/results/multiboot/e2.3 | 23 +++++++++++++++++++++++ grubby/test.sh | 18 ++++++++++++++++++ grubby/test/results/updargs/g3.7 | 4 ++-- 9 files changed, 211 insertions(+), 2 deletions(-) diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test.sh --- a/grubby/test.sh Thu Jun 29 16:56:35 2006 -0400 +++ b/grubby/test.sh Thu Jun 29 17:01:05 2006 -0400 @@ -334,6 +334,24 @@ grubTest grub.10 multiboot/g10.7 --boot- grubTest grub.10 multiboot/g10.7 --boot-filesystem=/boot \ --remove-multiboot=/boot/xen.gz +testing="ELILO add multiboot" +eliloTest elilo.1 multiboot/e1.1 --add-multiboot=/boot/xen.gz \ + --add-kernel=/boot/vmlinuz-2.6.10-1.1088_FC4 --boot-filesystem=/boot \ + --initrd=/boot/initrd-2.6.10-1.1088_FC4.img --title foo \ + --mbargs="dom0_mem=130000" +eliloTest elilo.1 multiboot/e1.2 --add-multiboot=/boot/xen.gz \ + --add-kernel=/boot/vmlinuz-2.6.10-1.1088_FC4 --boot-filesystem=/boot \ + --initrd=/boot/initrd-2.6.10-1.1088_FC4.img --title foo \ + --mbargs="dom0_mem=130000" --copy-default + +testing="ELILO remove multiboot" +eliloTest elilo.2 multiboot/e2.1 --boot-filesystem=/boot \ + --remove-kernel=/boot/vmlinuz-2.6.10-1.1076_FC4 +eliloTest elilo.2 multiboot/e2.2 --boot-filesystem=/boot \ + --remove-kernel=/boot/vmlinuz-2.6.10-1.1082_FC4 +eliloTest elilo.2 multiboot/e2.3 --boot-filesystem=/boot \ + --remove-multiboot=/boot/xen.gz + printf "\n%d (%d%%) tests passed, %d (%d%%) tests failed\n" \ $pass $(((100*pass)/(pass+fail))) \ $fail $(((100*fail)/(pass+fail))) diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/results/updargs/g3.7 --- a/grubby/test/results/updargs/g3.7 Thu Jun 29 16:56:35 2006 -0400 +++ b/grubby/test/results/updargs/g3.7 Thu Jun 29 17:01:05 2006 -0400 @@ -3,11 +3,11 @@ splashimage=(hd0,1)/grub/splash.xpm.gz splashimage=(hd0,1)/grub/splash.xpm.gz title Red Hat Linux (2.4.7-2smp) root (hd0,1) - kernel /vmlinuz-2.4.7-2smp + kernel /vmlinuz-2.4.7-2smp initrd /initrd-2.4.7-2smp.img title Red Hat Linux-up (2.4.7-2) root (hd0,1) - kernel /vmlinuz-2.4.7-2 + kernel /vmlinuz-2.4.7-2 initrd /initrd-2.4.7-2.img title DOS rootnoverify (hd0,0) diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/elilo.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grubby/test/elilo.1 Thu Jun 29 17:01:05 2006 -0400 @@ -0,0 +1,25 @@ +prompt +timeout=50 +default=linux +boot=/dev/md1 +map=/boot/map +install=/boot/boot.b +message=/boot/message +linear + +disk=/dev/sdm + bios=0x80 +disk=/dev/sdn + bios=0x81 + +image=/boot/vmlinuz-2.4.18-4 + label=linux-up + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4.img + +image=/boot/vmlinuz-2.4.18-4smp + label=linux + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4smp.img diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/elilo.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grubby/test/elilo.2 Thu Jun 29 17:01:05 2006 -0400 @@ -0,0 +1,30 @@ +prompt +timeout=50 +default=linux +boot=/dev/md1 +map=/boot/map +install=/boot/boot.b +message=/boot/message +linear + +disk=/dev/sdm + bios=0x80 +disk=/dev/sdn + bios=0x81 + +image=/vmlinuz-2.6.10-1.1076_FC4 + label=foo + initrd=/initrd-2.6.10-1.1088_FC4.img + append="dom0_mem=130000 --" +image=/boot/vmlinuz-2.4.18-4 + label=linux-up + vmm=/xen.gz + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4.img + +image=/vmlinuz-2.6.10-1.1082_FC4 + label=linux + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4smp.img diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/results/multiboot/e1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grubby/test/results/multiboot/e1.1 Thu Jun 29 17:01:05 2006 -0400 @@ -0,0 +1,30 @@ +prompt +timeout=50 +default=linux +boot=/dev/md1 +map=/boot/map +install=/boot/boot.b +message=/boot/message +linear + +disk=/dev/sdm + bios=0x80 +disk=/dev/sdn + bios=0x81 + +image=/vmlinuz-2.6.10-1.1088_FC4 + label=foo + vmm=/xen.gz + initrd=/initrd-2.6.10-1.1088_FC4.img + append="dom0_mem=130000 --" +image=/boot/vmlinuz-2.4.18-4 + label=linux-up + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4.img + +image=/boot/vmlinuz-2.4.18-4smp + label=linux + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4smp.img diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/results/multiboot/e1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grubby/test/results/multiboot/e1.2 Thu Jun 29 17:01:05 2006 -0400 @@ -0,0 +1,32 @@ +prompt +timeout=50 +default=linux +boot=/dev/md1 +map=/boot/map +install=/boot/boot.b +message=/boot/message +linear + +disk=/dev/sdm + bios=0x80 +disk=/dev/sdn + bios=0x81 + +image=/vmlinuz-2.6.10-1.1088_FC4 + vmm=/xen.gz + label=foo + root=/dev/md0 + read-only + initrd=/initrd-2.6.10-1.1088_FC4.img + append="dom0_mem=130000 --" +image=/boot/vmlinuz-2.4.18-4 + label=linux-up + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4.img + +image=/boot/vmlinuz-2.4.18-4smp + label=linux + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4smp.img diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/results/multiboot/e2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grubby/test/results/multiboot/e2.1 Thu Jun 29 17:01:05 2006 -0400 @@ -0,0 +1,26 @@ +prompt +timeout=50 +default=linux +boot=/dev/md1 +map=/boot/map +install=/boot/boot.b +message=/boot/message +linear + +disk=/dev/sdm + bios=0x80 +disk=/dev/sdn + bios=0x81 + +image=/boot/vmlinuz-2.4.18-4 + label=linux-up + vmm=/xen.gz + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4.img + +image=/vmlinuz-2.6.10-1.1082_FC4 + label=linux + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4smp.img diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/results/multiboot/e2.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grubby/test/results/multiboot/e2.2 Thu Jun 29 17:01:05 2006 -0400 @@ -0,0 +1,25 @@ +prompt +timeout=50 +default=foo +boot=/dev/md1 +map=/boot/map +install=/boot/boot.b +message=/boot/message +linear + +disk=/dev/sdm + bios=0x80 +disk=/dev/sdn + bios=0x81 + +image=/vmlinuz-2.6.10-1.1076_FC4 + label=foo + initrd=/initrd-2.6.10-1.1088_FC4.img + append="dom0_mem=130000 --" +image=/boot/vmlinuz-2.4.18-4 + label=linux-up + vmm=/xen.gz + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4.img + diff -r bbebf7a97ae1 -r c21b0cf582a1 grubby/test/results/multiboot/e2.3 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grubby/test/results/multiboot/e2.3 Thu Jun 29 17:01:05 2006 -0400 @@ -0,0 +1,23 @@ +prompt +timeout=50 +default=linux +boot=/dev/md1 +map=/boot/map +install=/boot/boot.b +message=/boot/message +linear + +disk=/dev/sdm + bios=0x80 +disk=/dev/sdn + bios=0x81 + +image=/vmlinuz-2.6.10-1.1076_FC4 + label=foo + initrd=/initrd-2.6.10-1.1088_FC4.img + append="dom0_mem=130000 --" +image=/vmlinuz-2.6.10-1.1082_FC4 + label=linux + root=/dev/md0 + read-only + initrd=/boot/initrd-2.4.18-4smp.img
Aron Griffis
2006-Jun-29 21:42 UTC
[Fedora-xen] [PATCH 6 of 6] Update new-kernel-pkg to support elilo w/ multiboot
# HG changeset patch # User agriffis@cheo.zko.hp.com # Node ID c4bc9fbc2487083f4033f498cd7e6f1efd7af6bf # Parent c21b0cf582a12df3f29601fca13f9ac82cf0ff06 Update new-kernel-pkg to support elilo w/ multiboot Additionally fix multiple /sbin/grubby instances to use the variable from the top of the script. Signed-off-by: Aron Griffis <aron@hp.com> new-kernel-pkg | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff -r c21b0cf582a1 -r c4bc9fbc2487 grubby/new-kernel-pkg --- a/grubby/new-kernel-pkg Thu Jun 29 17:01:05 2006 -0400 +++ b/grubby/new-kernel-pkg Thu Jun 29 17:06:02 2006 -0400 @@ -125,7 +125,7 @@ install() { fi fi - if [ -n "$mbkernel" ]; then + if [ -n "$mbkernel" -a -n "$cfgLilo" -a "$liloFlag" != "elilo" ]; then [ -n "$verbose" ] && echo "multiboot specified, not updating lilo.conf" cfgLilo="" fi @@ -140,7 +140,7 @@ install() { else title="Red Hat Linux ($version)" fi - /sbin/grubby --add-kernel=$bootPrefix/$kernelName-$version \ + $grubby --add-kernel=$bootPrefix/$kernelName-$version \ $INITRD --copy-default $makedefault --title "$title" \ ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" @@ -151,11 +151,11 @@ install() { if [ -n "$cfgLilo" ]; then [ -n "$verbose" ] && echo "adding $version to $liloConfig" - /sbin/grubby --add-kernel=$bootPrefix/$kernelName-$version $INITRD \ - --copy-default $makedefault --title $version \ - --args="root=$rootdevice $kernargs" \ - --remove-kernel="TITLE=$version" \ - --$liloFlag + $grubby --add-kernel=$bootPrefix/$kernelName-$version $INITRD \ + --copy-default $makedefault --title $version \ + ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ + --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$version" \ + --$liloFlag if [ -n "$runLilo" ]; then [ -n "$verbose" ] && echo "running $lilo" @@ -181,14 +181,14 @@ remove() { if [ -n "$cfgGrub" ]; then [ -n "$verbose" ] && echo "removing $version from $grubConfig" - /sbin/grubby --remove-kernel=$bootPrefix/$kernelName-$version + $grubby --remove-kernel=$bootPrefix/$kernelName-$version else [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby" fi if [ -n "$cfgLilo" ]; then [ -n "$verbose" ] && echo "removing $version from $liloConfig" - /sbin/grubby --remove-kernel=$bootPrefix/$kernelName-$version \ + $grubby --remove-kernel=$bootPrefix/$kernelName-$version \ --$liloFlag if [ -n "$runLilo" ]; then @@ -207,7 +207,7 @@ update() { update() { if [ -n "$cfgGrub" ]; then [ -n "$verbose" ] && echo "updating $version from $grubConfig" - /sbin/grubby --update-kernel=$bootPrefix/$kernelName-$version \ + $grubby --update-kernel=$bootPrefix/$kernelName-$version \ ${kernargs:+--args="$kernargs"} \ ${removeargs:+--remove-args="$removeargs"} else @@ -216,7 +216,7 @@ update() { if [ -n "$cfgLilo" ]; then [ -n "$verbose" ] && echo "updating $version from $liloConfig" - /sbin/grubby --update-kernel=$bootPrefix/$kernelName-$version \ + $grubby --update-kernel=$bootPrefix/$kernelName-$version \ ${kernargs:+--args="$kernargs"} \ ${removeargs:+--remove-args="$removeargs"} \ --$liloFlag
On Thu, 2006-06-29 at 17:42 -0400, Aron Griffis wrote:> - By default, run all the tests, regardless of architecture. Since the test > suite calls grubby and not the bootloaders themselves, there''s no reason to > be selective.There was a reason why I changed this to be the way it is at one point... hell if I remember what it is anymore. Since things seem to work, I''m willing to give it a try again :)> - NB: These changes reveal that yaboot parsing has some issues.Well, more just that it reorders the file rather than actual issues. Fixed up the tests -- the reordering actually doesn''t cause any problems for yaboot.> Additionally > the symlink test now returns failure, which wasn''t being detected properly > before.Indeed. Fixed up the code for this to actually be correct. Jeremy
Jeremy Katz
2006-Jun-30 04:03 UTC
[Fedora-xen] Re: [PATCH 0 of 6] elilo multiboot support (take 2)
On Thu, 2006-06-29 at 17:42 -0400, Aron Griffis wrote:> The following patches give grubby the ability to manipulate > multiboot-capable elilo.conf. Fedora''s elilo already contains the > support, these patches simply teach grubby to take advantage of it. > These patches are an enabler for using Xen on ia64 with Fedora.Looks good -- I''ve applied all of these and they''ll be in the mkinitrd build I''m going to push through the buildsys now. Jeremy