# Grub

Parses grub configuration

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

Summary

Grub | Parses grub configuration
License | This file is licenced under the LGPL v2+, like the rest of Augeas.
Lens Usage | To 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 |
error | Parse a line that looks almost like a valid setting, but isn’t, into an ‘#error’ node.
BOOT ENTRIES |
device | 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 |
serial |
terminal |
setkey |
menu_entry |
menu_error | Accept lines not matching menu_entry and stuff them into ‘#error’ nodes
menu_setting | a valid menu setting or a line that looks like one but is an #error
title |
multiboot_arg | Permits a second form for Solaris multiboot kernels that take a path (with a slash) as their first arg, e.g.
kernel_args | Parse the file name and args on a kernel or module line.
module_line | Solaris extension adds module$ and kernel$ for variable interpolation
map_line |
kernel |
chainloader |
savedefault |
configfile |
boot_entry | boot entries
boot_error | Accept lines not matching boot_entry and stuff them into ‘#error’ nodes
boot_setting | a valid boot setting or a line that looks like one but is an #error
boot |
DEBIAN-SPECIFIC SECTIONS |
debian_header | Header for a debian-specific section
debian_footer | Footer for a debian-specific section
debian_comment_re |
debian_comment | A comment entry inside a debian-specific section
debian_setting_re |
debian_entry |
debian | A 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:regexp | the 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