Bump to 1.14.1
[platform/upstream/augeas.git] / lenses / grub.aug
1 (*
2 Module: Grub
3   Parses grub configuration
4
5 Author: David Lutterkort <lutter@redhat.com>
6
7 About: License
8    This file is licenced under the LGPL v2+, like the rest of Augeas.
9
10 About: Lens Usage
11    To be documented
12 *)
13
14 module Grub =
15   autoload xfm
16
17     (* This only covers the most basic grub directives. Needs to be *)
18     (* expanded to cover more (and more esoteric) directives        *)
19     (* It is good enough to handle the grub.conf on my Fedora 8 box *)
20
21
22 (************************************************************************
23  * Group:                 USEFUL PRIMITIVES
24  *************************************************************************)
25
26     (* View: value_to_eol *)
27     let value_to_eol = store /[^= \t\n][^\n]*[^= \t\n]|[^= \t\n]/
28
29     (* View: eol *)
30     let eol = Util.eol
31
32     (* View: spc *)
33     let spc = Util.del_ws_spc
34
35     (* View: opt_ws *)
36     let opt_ws = Util.del_opt_ws ""
37
38     (* View: dels *)
39     let dels (s:string) = Util.del_str s
40
41     (* View: eq *)
42     let eq = dels "="
43
44     (* View: switch *)
45     let switch (n:regexp) = dels "--" . key n
46
47     (* View: switch_arg *)
48     let switch_arg (n:regexp) = switch n . eq . store Rx.no_spaces
49
50     (* View: value_sep *)
51     let value_sep (dflt:string) = del /[ \t]*[ \t=][ \t]*/ dflt
52
53     (* View: comment_re *)
54     let comment_re = /([^ \t\n].*[^ \t\n]|[^ \t\n])/
55                        - /# ## (Start|End) Default Options ##/
56
57     (* View: comment *)
58     let comment    =
59         [ Util.indent . label "#comment" . del /#[ \t]*/ "# "
60             . store comment_re . eol ]
61
62     (* View: empty *)
63     let empty   = Util.empty
64
65 (************************************************************************
66  * Group:                 USEFUL FUNCTIONS
67  *************************************************************************)
68
69     (* View: command *)
70     let command (kw:regexp) (indent:string) =
71       Util.del_opt_ws indent . key kw
72
73     (* View: kw_arg *)
74     let kw_arg (kw:regexp) (indent:string) (dflt_sep:string) =
75       [ command kw indent . value_sep dflt_sep . value_to_eol . eol ]
76
77     (* View: kw_boot_arg *)
78     let kw_boot_arg (kw:regexp) = kw_arg kw "\t" " "
79
80     (* View: kw_menu_arg *)
81     let kw_menu_arg (kw:regexp) = kw_arg kw "" " "
82
83     (* View: password_arg *)
84     let password_arg = [ command "password" "" .
85       (spc . [ switch "md5" ])? .
86       (spc . [ switch "encrypted" ])? .
87       spc . store (/[^ \t\n]+/ - /--[^ \t\n]+/) .
88       (spc . [ label "file" . store /[^ \t\n]+/ ])? .
89       eol ]
90
91     (* View: kw_pres *)
92     let kw_pres (kw:string) = [ opt_ws . key kw . eol ]
93
94     (* View: error
95      *   Parse a line that looks almost like a valid setting, but isn't,
96      *   into an '#error' node. Any line that starts with letters, but not
97      *   anything matching kw, is considered an error line.
98      *
99      *   Parameters:
100      *     kw:regexp - the valid keywords that are _not_ considered an
101      *                 error
102      *)
103     let error (kw:regexp) =
104       let not_kw = /[a-zA-Z]+/ - kw in
105       [ label "#error" . Util.del_opt_ws "\t"
106         . store (not_kw . /([^a-zA-Z\n].*[^ \t\n])?/) . eol ]
107
108
109 (************************************************************************
110  * Group:                 BOOT ENTRIES
111  *************************************************************************)
112
113     (* View: device
114      *  This is a shell-only directive in upstream grub; the grub versions
115      *  in at least Fedora/RHEL use this to find devices for UEFI boot *)
116     let device =
117       [ command "device" "" . Sep.space . store /\([A-Za-z0-9_.-]+\)/ . spc .
118         [ label "file" . value_to_eol ] . Util.eol ]
119
120     (* View: color *)
121     let color =
122       (* Should we nail it down to exactly the color names that *)
123       (* grub supports ? *)
124       let color_name = store /[A-Za-z-]+/ in
125       let color_spec =
126         [ label "foreground" . color_name] .
127         dels "/" .
128         [ label "background" . color_name ] in
129       [ opt_ws . key "color" .
130         spc . [ label "normal" . color_spec ] .
131         (spc . [ label "highlight" . color_spec ])? .
132         eol ]
133
134     (* View: serial *)
135     let serial =
136       [ command "serial" "" .
137         [ spc . switch_arg /unit|port|speed|word|parity|stop|device/ ]* .
138         eol ]
139
140     (* View: terminal *)
141     let terminal =
142       [ command "terminal" "" .
143           ([ spc . switch /dumb|no-echo|no-edit|silent/ ]
144           |[ spc . switch_arg /timeout|lines/ ])* .
145           [ spc . key /console|serial|hercules/ ]* . eol ]
146
147     (* View: setkey *)
148     let setkey = [ command "setkey" "" .
149       ( spc . [ label "to" . store Rx.no_spaces ] .
150         spc . [ label "from" . store Rx.no_spaces ] )? .
151       eol ]
152
153     (* View: menu_entry *)
154     let menu_entry = kw_menu_arg "default"
155                      | kw_menu_arg "fallback"
156                      | kw_pres "hiddenmenu"
157                      | kw_menu_arg "timeout"
158                      | kw_menu_arg "splashimage"
159                      | kw_menu_arg "gfxmenu"
160                      | kw_menu_arg "foreground"
161                      | kw_menu_arg "background"
162                      | kw_menu_arg "verbose"
163                      | kw_menu_arg "boot" (* only for CLI, ignored in conf *)
164                      | serial
165                      | terminal
166                      | password_arg
167                      | color
168                      | device
169                      | setkey
170
171     (* View: menu_error
172      *   Accept lines not matching menu_entry and stuff them into
173      *   '#error' nodes
174      *)
175     let menu_error =
176       let kw = /default|fallback|hiddenmenu|timeout|splashimage|gfxmenu/
177              |/foreground|background|verbose|boot|password|title/
178              |/serial|setkey|terminal|color|device/ in
179       error kw
180
181     (* View: menu_setting
182      *   a valid menu setting or a line that looks like one but is an #error
183      *)
184     let menu_setting = menu_entry | menu_error
185
186     (* View: title *)
187     let title = del /title[ \t=]+/ "title " . value_to_eol . eol
188
189     (* View: multiboot_arg
190      *  Permits a second form for Solaris multiboot kernels that
191      *  take a path (with a slash) as their first arg, e.g.
192      *  /boot/multiboot kernel/unix another=arg *)
193     let multiboot_arg = [ label "@path" .
194                           store (Rx.word . "/" . Rx.no_spaces) ]
195
196     (* View: kernel_args
197         Parse the file name and args on a kernel or module line. *)
198     let kernel_args =
199       let arg = /[A-Za-z0-9_.$\+-]+/ - /type|no-mem-option/  in
200       store /(\([a-z0-9,]+\))?\/[^ \t\n]*/ .
201             (spc . multiboot_arg)? .
202             (spc . [ key arg . (eq. store /([^ \t\n])*/)?])* . eol
203
204     (* View: module_line
205         Solaris extension adds module$ and kernel$ for variable interpolation *)
206     let module_line =
207       [ command /module\$?/ "\t" . spc . kernel_args ]
208
209     (* View: map_line *)
210     let map_line =
211       [ command "map" "\t" . spc .
212            [ label "from" . store /[()A-za-z0-9]+/ ] . spc .
213            [ label "to" . store /[()A-za-z0-9]+/ ] . eol ]
214
215     (* View: kernel *)
216     let kernel =
217         [ command /kernel\$?/ "\t" .
218           (spc .
219              ([switch "type" . eq . store /[a-z]+/]
220              |[switch "no-mem-option"]))* .
221           spc . kernel_args ]
222
223     (* View: chainloader *)
224     let chainloader =
225       [ command "chainloader" "\t" .
226           [ spc . switch "force" ]? . spc . store Rx.no_spaces . eol ]
227
228     (* View: savedefault *)
229     let savedefault =
230       [ command "savedefault" "\t" . (spc . store Rx.integer)? . eol ]
231
232     (* View: configfile *)
233     let configfile =
234       [ command "configfile" "\t" . spc . store Rx.no_spaces . eol ]
235
236     (* View: boot_entry
237         <boot> entries *)
238     let boot_entry =
239           let boot_arg_re = "root" | "initrd" | "rootnoverify" | "uuid"
240                           | "findroot" | "bootfs" (* Solaris extensions *)
241        in kw_boot_arg boot_arg_re
242         | kernel
243         | chainloader
244         | kw_pres "quiet"  (* Seems to be a Ubuntu extension *)
245         | savedefault
246         | configfile
247         | module_line
248         | map_line
249         | kw_pres "lock"
250         | kw_pres "makeactive"
251         | password_arg
252
253     (* View: boot_error
254      *   Accept lines not matching boot_entry and stuff them into
255      *   '#error' nodes
256      *)
257     let boot_error =
258       let kw = /lock|uuid|password|root|initrd|rootnoverify|findroot|bootfs/
259              |/configfile|chainloader|title|boot|quiet|kernel|module/
260              |/makeactive|savedefault|map/ in
261       error kw
262
263     (* View: boot_setting
264      *   a valid boot setting or a line that looks like one but is an #error
265      *)
266     let boot_setting = boot_entry | boot_error
267
268     (* View: boot *)
269     let boot =
270       let line = ((boot_setting|comment)* . boot_setting)? in
271       [ label "title" . title . line ]
272
273 (************************************************************************
274  * Group:                 DEBIAN-SPECIFIC SECTIONS
275  *************************************************************************)
276
277     (* View: debian_header
278         Header for a <debian>-specific section *)
279     let debian_header  = "## ## Start Default Options ##\n"
280
281     (* View: debian_footer
282         Footer for a <debian>-specific section *)
283     let debian_footer  = "## ## End Default Options ##\n"
284
285     (* View: debian_comment_re *)
286     let debian_comment_re = /([^ \t\n].*[^ \t\n]|[^ \t\n])/
287                             - "## End Default Options ##"
288
289     (* View: debian_comment
290         A comment entry inside a <debian>-specific section *)
291     let debian_comment =
292         [ Util.indent . label "#comment" . del /##[ \t]*/ "## "
293             . store debian_comment_re . eol ]
294
295     (* View: debian_setting_re *)
296     let debian_setting_re = "kopt"
297                           | "groot"
298                           | "alternative"
299                           | "lockalternative"
300                           | "defoptions"
301                           | "lockold"
302                           | "xenhopt"
303                           | "xenkopt"
304                           | "altoptions"
305                           | "howmany"
306                           | "memtest86"
307                           | "updatedefaultentry"
308                           | "savedefault"
309                           | "indomU"
310
311     (* View: debian_entry *)
312     let debian_entry   = [ Util.del_str "#" . Util.indent
313                          . key debian_setting_re . del /[ \t]*=/ "="
314                          . value_to_eol? . eol ]
315
316     (* View: debian
317         A debian-specific section, made of <debian_entry> lines *)
318     let debian         = [ label "debian"
319                     . del debian_header debian_header
320                     . (debian_comment|empty|debian_entry)*
321                     . del debian_footer debian_footer ]
322
323 (************************************************************************
324  * Group:                 LENS AND FILTER
325  *************************************************************************)
326
327     (* View: lns *)
328     let lns = (comment | empty | menu_setting | debian)*
329       . (boot . (comment | empty | boot)*)?
330
331     (* View: filter *)
332     let filter = incl "/boot/grub/grub.conf"
333                . incl "/boot/grub/menu.lst"
334                . incl "/etc/grub.conf"
335                . incl "/boot/efi/EFI/*/grub.conf"
336
337     let xfm = transform lns filter