Grub

Parses grub configuration

Author: David Lutterkort lut.nosp@m.ter@redha.nosp@m.t.com

Summary
GrubParses grub configuration
LicenseThis file is licenced under the LGPL v2+, like the rest of Augeas.
Lens UsageTo be documented
USEFUL PRIMITIVES
value_to_eol
eol
spc
opt_ws
dels
eq
switch
switch_arg
value_sep
comment_re
comment
empty
USEFUL FUNCTIONS
command
kw_arg
kw_boot_arg
kw_menu_arg
password_arg
kw_pres
errorParse a line that looks almost like a valid setting, but isn’t, into an ‘#error’ node.
BOOT ENTRIES
deviceThis is a shell-only directive in upstream grub; the grub versions in at least Fedora/RHEL use this to find devices for UEFI boot
color
serial
terminal
setkey
menu_entry
menu_errorAccept lines not matching menu_entry and stuff them into ‘#error’ nodes
menu_settinga valid menu setting or a line that looks like one but is an #error
title
multiboot_argPermits a second form for Solaris multiboot kernels that take a path (with a slash) as their first arg, e.g.
kernel_argsParse the file name and args on a kernel or module line.
module_lineSolaris extension adds module$ and kernel$ for variable interpolation
map_line
kernel
chainloader
savedefault
configfile
boot_entryboot entries
boot_errorAccept lines not matching boot_entry and stuff them into ‘#error’ nodes
boot_settinga valid boot setting or a line that looks like one but is an #error
boot
DEBIAN-SPECIFIC SECTIONS
debian_headerHeader for a debian-specific section
debian_footerFooter for a debian-specific section
debian_comment_re
debian_commentA comment entry inside a debian-specific section
debian_setting_re
debian_entry
debianA debian-specific section, made of debian_entry lines
LENS AND FILTER
lns
filter

License

This file is licenced under the LGPL v2+, like the rest of Augeas.

Lens Usage

To be documented

USEFUL PRIMITIVES

value_to_eol

let value_to_eol = store /[^= \t\n][^\n]*[^= \t\n]|[^= \t\n]/

eol

let eol = Util.eol

spc

let spc = Util.del_ws_spc

opt_ws

let opt_ws = Util.del_opt_ws ""

dels

let dels (s:string) = Util.del_str s

eq

let eq = dels "="

switch

let switch (n:regexp) = dels "--" . key n

switch_arg

let switch_arg (n:regexp) = switch n . eq . store Rx.no_spaces

value_sep

let value_sep (dflt:string) = del /[ \t]*[ \t=][ \t]*/ dflt

comment_re

let comment_re = /([^ \t\n].*[^ \t\n]|[^ \t\n])/ - /# ## (Start|End) Default Options ##/

comment

let comment = [ Util.indent . label "#comment" . del /#[ \t]*/ "# " . store comment_re . eol ]

empty

let empty = Util.empty

USEFUL FUNCTIONS

command

let command (kw:regexp) (indent:string) = Util.del_opt_ws indent . key kw

kw_arg

let kw_arg (kw:regexp) (indent:string) (dflt_sep:string) = [ command kw indent . value_sep dflt_sep . value_to_eol . eol ]

kw_boot_arg

let kw_boot_arg (kw:regexp) = kw_arg kw "\t" " "

kw_menu_arg

let kw_menu_arg (kw:regexp) = kw_arg kw "" " "

password_arg

let password_arg = [ command "password" "" . (spc . [ switch "md5" ])? . (spc . [ switch "encrypted" ])? . spc . store (/[^ \t\n]+/ - /--[^ \t\n]+/) . (spc . [ label "file" . store /[^ \t\n]+/ ])? . eol ]

kw_pres

let kw_pres (kw:string) = [ opt_ws . key kw . eol ]

error

let error (kw:regexp) = let not_kw = /[a-zA-Z]+/ - kw in [ label "#error" . Util.del_opt_ws "\t" . store (not_kw . /([^a-zA-Z\n].*[^ \t\n])?/) . eol ]

Parse a line that looks almost like a valid setting, but isn’t, into an ‘#error’ node.  Any line that starts with letters, but not anything matching kw, is considered an error line.

Parameters

kw:regexpthe valid keywords that are not considered an error

BOOT ENTRIES

device

let device = [ command "device" "" . Sep.space . store /\([A-Za-z0-9_.-]+\)/ . spc . [ label "file" . value_to_eol ] . Util.eol ]

This is a shell-only directive in upstream grub; the grub versions in at least Fedora/RHEL use this to find devices for UEFI boot

color

let color =

serial

let serial = [ command "serial" "" . [ spc . switch_arg /unit|port|speed|word|parity|stop|device/ ]* . eol ]

terminal

let terminal = [ command "terminal" "" . ([ spc . switch /dumb|no-echo|no-edit|silent/ ] |[ spc . switch_arg /timeout|lines/ ])* . [ spc . key /console|serial|hercules/ ]* . eol ]

setkey

let setkey = [ command "setkey" "" . ( spc . [ label "to" . store Rx.no_spaces ] . spc . [ label "from" . store Rx.no_spaces ] )? . eol ]

menu_entry

let menu_entry = kw_menu_arg "default" | kw_menu_arg "fallback" | kw_pres "hiddenmenu" | kw_menu_arg "timeout" | kw_menu_arg "splashimage" | kw_menu_arg "gfxmenu" | kw_menu_arg "foreground" | kw_menu_arg "background" | kw_menu_arg "verbose" | kw_menu_arg "boot" (* only for CLI, ignored in conf *) | serial | terminal | password_arg | color | device | setkey

menu_error

let menu_error = let kw = /default|fallback|hiddenmenu|timeout|splashimage|gfxmenu/ |/foreground|background|verbose|boot|password|title/ |/serial|setkey|terminal|color|device/ in error kw

Accept lines not matching menu_entry and stuff them into ‘#error’ nodes

menu_setting

let menu_setting = menu_entry | menu_error

a valid menu setting or a line that looks like one but is an #error

title

let title = del /title[ \t=]+/ "title " . value_to_eol . eol

multiboot_arg

let multiboot_arg = [ label "@path" . store (Rx.word . "/" . Rx.no_spaces) ]

Permits a second form for Solaris multiboot kernels that take a path (with a slash) as their first arg, e.g.  /boot/multiboot kernel/unix another=arg

kernel_args

let kernel_args = let arg = /[A-Za-z0-9_.$-]+/ - /type|no-mem-option/ in store /(\([a-z0-9,]+\))?\/[^ \t\n]*/ . (spc . multiboot_arg)? . (spc . [ key arg . (eq. store /([^ \t\n])*/)?])* . eol

Parse the file name and args on a kernel or module line.

module_line

let module_line = [ command /module\$?/ "\t" . spc . kernel_args ]

Solaris extension adds module$ and kernel$ for variable interpolation

map_line

let map_line = [ command "map" "\t" . spc . [ label "from" . store /[()A-za-z0-9]+/ ] . spc . [ label "to" . store /[()A-za-z0-9]+/ ] . eol ]

kernel

let kernel = [ command /kernel\$?/ "\t" . (spc . ([switch "type" . eq . store /[a-z]+/] |[switch "no-mem-option"]))* . spc . kernel_args ]

chainloader

let chainloader = [ command "chainloader" "\t" . [ spc . switch "force" ]? . spc . store Rx.no_spaces . eol ]

savedefault

let savedefault = [ command "savedefault" "\t" . (spc . store Rx.integer)? . eol ]

configfile

let configfile = [ command "configfile" "\t" . spc . store Rx.no_spaces . eol ]

boot_entry

let boot_entry = let boot_arg_re = "root" | "initrd" | "rootnoverify" | "uuid" | "findroot" | "bootfs" (* Solaris extensions *) in kw_boot_arg boot_arg_re | kernel | chainloader | kw_pres "quiet" (* Seems to be a Ubuntu extension *) | savedefault | configfile | module_line | map_line | kw_pres "lock" | kw_pres "makeactive" | password_arg

boot entries

boot_error

let boot_error = let kw = /lock|uuid|password|root|initrd|rootnoverify|findroot|bootfs/ |/configfile|chainloader|title|boot|quiet|kernel|

Accept lines not matching boot_entry and stuff them into ‘#error’ nodes

boot_setting

let boot_setting = boot_entry | boot_error

a valid boot setting or a line that looks like one but is an #error

boot

let boot = let line = ((boot_setting|comment)* . boot_setting)? in [ label "title" . title . line ]

DEBIAN-SPECIFIC SECTIONS

debian_header

let debian_header = "## ## Start Default Options ##\n"

Header for a debian-specific section

debian_footer

let debian_footer = "## ## End Default Options ##\n"

Footer for a debian-specific section

debian_comment_re

let debian_comment_re = /([^ \t\n].*[^ \t\n]|[^ \t\n])/ - "## End Default Options ##"

debian_comment

let debian_comment = [ Util.indent . label "#comment" . del /##[ \t]*/ "## " . store debian_comment_re . eol ]

A comment entry inside a debian-specific section

debian_setting_re

let debian_setting_re = "kopt" | "groot" | "alternative" | "lockalternative" | "defoptions" | "lockold" | "xenhopt" | "xenkopt" | "altoptions" | "howmany" | "memtest86" | "updatedefaultentry" | "savedefault" | "indomU"

debian_entry

let debian_entry = [ Util.del_str "#" . Util.indent . key debian_setting_re . del /[ \t]*=/ "=" . value_to_eol? . eol ]

debian

let debian = [ label "debian" . del debian_header debian_header . (debian_comment|empty|debian_entry)* . del debian_footer debian_footer ]

A debian-specific section, made of debian_entry lines

LENS AND FILTER

lns

let lns = (comment | empty | menu_setting | debian)* . (boot . (comment | empty | boot)*)?

filter

let value_to_eol = store /[^= \t\n][^\n]*[^= \t\n]|[^= \t\n]/
let eol = Util.eol
let spc = Util.del_ws_spc
let opt_ws = Util.del_opt_ws ""
let dels (s:string) = Util.del_str s
let eq = dels "="
let switch (n:regexp) = dels "--" . key n
let switch_arg (n:regexp) = switch n . eq . store Rx.no_spaces
let value_sep (dflt:string) = del /[ \t]*[ \t=][ \t]*/ dflt
let comment_re = /([^ \t\n].*[^ \t\n]|[^ \t\n])/ - /# ## (Start|End) Default Options ##/
let comment = [ Util.indent . label "#comment" . del /#[ \t]*/ "# " . store comment_re . eol ]
let empty = Util.empty
let command (kw:regexp) (indent:string) = Util.del_opt_ws indent . key kw
let kw_arg (kw:regexp) (indent:string) (dflt_sep:string) = [ command kw indent . value_sep dflt_sep . value_to_eol . eol ]
let kw_boot_arg (kw:regexp) = kw_arg kw "\t" " "
let kw_menu_arg (kw:regexp) = kw_arg kw "" " "
let password_arg = [ command "password" "" . (spc . [ switch "md5" ])? . (spc . [ switch "encrypted" ])? . spc . store (/[^ \t\n]+/ - /--[^ \t\n]+/) . (spc . [ label "file" . store /[^ \t\n]+/ ])? . eol ]
let kw_pres (kw:string) = [ opt_ws . key kw . eol ]
let error (kw:regexp) = let not_kw = /[a-zA-Z]+/ - kw in [ label "#error" . Util.del_opt_ws "\t" . store (not_kw . /([^a-zA-Z\n].*[^ \t\n])?/) . eol ]
Parse a line that looks almost like a valid setting, but isn’t, into an ‘#error’ node.
let device = [ command "device" "" . Sep.space . store /\([A-Za-z0-9_.-]+\)/ . spc . [ label "file" . value_to_eol ] . Util.eol ]
This is a shell-only directive in upstream grub; the grub versions in at least Fedora/RHEL use this to find devices for UEFI boot
let color =
let serial = [ command "serial" "" . [ spc . switch_arg /unit|port|speed|word|parity|stop|device/ ]* . eol ]
let terminal = [ command "terminal" "" . ([ spc . switch /dumb|no-echo|no-edit|silent/ ] |[ spc . switch_arg /timeout|lines/ ])* . [ spc . key /console|serial|hercules/ ]* . eol ]
let setkey = [ command "setkey" "" . ( spc . [ label "to" . store Rx.no_spaces ] . spc . [ label "from" . store Rx.no_spaces ] )? . eol ]
let menu_entry = kw_menu_arg "default" | kw_menu_arg "fallback" | kw_pres "hiddenmenu" | kw_menu_arg "timeout" | kw_menu_arg "splashimage" | kw_menu_arg "gfxmenu" | kw_menu_arg "foreground" | kw_menu_arg "background" | kw_menu_arg "verbose" | kw_menu_arg "boot" (* only for CLI, ignored in conf *) | serial | terminal | password_arg | color | device | setkey
let menu_error = let kw = /default|fallback|hiddenmenu|timeout|splashimage|gfxmenu/ |/foreground|background|verbose|boot|password|title/ |/serial|setkey|terminal|color|device/ in error kw
Accept lines not matching menu_entry and stuff them into ‘#error’ nodes
let menu_setting = menu_entry | menu_error
a valid menu setting or a line that looks like one but is an #error
let title = del /title[ \t=]+/ "title " . value_to_eol . eol
let multiboot_arg = [ label "@path" . store (Rx.word . "/" . Rx.no_spaces) ]
Permits a second form for Solaris multiboot kernels that take a path (with a slash) as their first arg, e.g.
let kernel_args = let arg = /[A-Za-z0-9_.$-]+/ - /type|no-mem-option/ in store /(\([a-z0-9,]+\))?\/[^ \t\n]*/ . (spc . multiboot_arg)? . (spc . [ key arg . (eq. store /([^ \t\n])*/)?])* . eol
Parse the file name and args on a kernel or module line.
let module_line = [ command /module\$?/ "\t" . spc . kernel_args ]
Solaris extension adds module$ and kernel$ for variable interpolation
let map_line = [ command "map" "\t" . spc . [ label "from" . store /[()A-za-z0-9]+/ ] . spc . [ label "to" . store /[()A-za-z0-9]+/ ] . eol ]
let kernel = [ command /kernel\$?/ "\t" . (spc . ([switch "type" . eq . store /[a-z]+/] |[switch "no-mem-option"]))* . spc . kernel_args ]
let chainloader = [ command "chainloader" "\t" . [ spc . switch "force" ]? . spc . store Rx.no_spaces . eol ]
let savedefault = [ command "savedefault" "\t" . (spc . store Rx.integer)? . eol ]
let configfile = [ command "configfile" "\t" . spc . store Rx.no_spaces . eol ]
let boot_entry = let boot_arg_re = "root" | "initrd" | "rootnoverify" | "uuid" | "findroot" | "bootfs" (* Solaris extensions *) in kw_boot_arg boot_arg_re | kernel | chainloader | kw_pres "quiet" (* Seems to be a Ubuntu extension *) | savedefault | configfile | module_line | map_line | kw_pres "lock" | kw_pres "makeactive" | password_arg
boot entries
let boot = let line = ((boot_setting|comment)* . boot_setting)? in [ label "title" . title . line ]
let boot_error = let kw = /lock|uuid|password|root|initrd|rootnoverify|findroot|bootfs/ |/configfile|chainloader|title|boot|quiet|kernel|
Accept lines not matching boot_entry and stuff them into ‘#error’ nodes
let boot_setting = boot_entry | boot_error
a valid boot setting or a line that looks like one but is an #error
let debian_header = "## ## Start Default Options ##\n"
Header for a debian-specific section
let debian = [ label "debian" . del debian_header debian_header . (debian_comment|empty|debian_entry)* . del debian_footer debian_footer ]
A debian-specific section, made of debian_entry lines
let debian_footer = "## ## End Default Options ##\n"
Footer for a debian-specific section
let debian_comment_re = /([^ \t\n].*[^ \t\n]|[^ \t\n])/ - "## End Default Options ##"
let debian_comment = [ Util.indent . label "#comment" . del /##[ \t]*/ "## " . store debian_comment_re . eol ]
A comment entry inside a debian-specific section
let debian_setting_re = "kopt" | "groot" | "alternative" | "lockalternative" | "defoptions" | "lockold" | "xenhopt" | "xenkopt" | "altoptions" | "howmany" | "memtest86" | "updatedefaultentry" | "savedefault" | "indomU"
let debian_entry = [ Util.del_str "#" . Util.indent . key debian_setting_re . del /[ \t]*=/ "=" . value_to_eol? . eol ]
let lns = (comment | empty | menu_setting | debian)* . (boot . (comment | empty | boot)*)?
Close