123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501(*
* Copyright (c) 2015 Gabriel Radanne <drupyog@zoho.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)openFunctoriamoduleKey=KeymoduleAlias=Key.AliasopenAstring(** {2 Custom Descriptions} *)moduleArg=structincludeKey.Argletfrom_runs="Mirage_runtime.Arg."^sletmakedmof_stringto_string=letparsers=matchof_stringswith|Error(`Msgm)->`Error("Can't parse ip address: "^s^": "^m)|Okip->`Okipandserializeppft=Fmt.pfppf"(%s.of_string_exn %S)"m(to_stringt)andppppft=Fmt.stringppf(to_stringt)inKey.Arg.conv~conv:(parser,pp)~serialize~runtime_conv:(from_rund)moduletypeS=sigtypetvalof_string:string->(t,[`Msgofstring])resultvalto_string:t->stringendletof_module(typet)dm(moduleM:Swithtypet=t)=makedmM.of_stringM.to_stringletipv4_address=of_module"ipv4_address""Ipaddr.V4"(moduleIpaddr.V4)letipv4=of_module"ipv4""Ipaddr.V4.Prefix"(moduleIpaddr.V4.Prefix)letipv6_address=of_module"ipv6_address""Ipaddr.V6"(moduleIpaddr.V6)letipv6=of_module"ipv6""Ipaddr.V6.Prefix"(moduleIpaddr.V6.Prefix)letip_address=of_module"ip_address""Ipaddr"(moduleIpaddr)end(** {2 Documentation helper} *)letmirage_section="MIRAGE PARAMETERS"letunikernel_section="UNIKERNEL PARAMETERS"letpp_group=Fmt.(option~none:(any"the unikernel")@@fmt"the %s group")(** {2 Special keys} *)(** {3 Mode} *)typemode_unix=[`Unix|`MacOSX]typemode_xen=[`Xen|`Qubes]typemode_solo5=[`Hvt|`Spt|`Virtio|`Muen|`Genode]typemode=[mode_unix|mode_xen|mode_solo5]lettarget_conv:modeCmdliner.Arg.conv=letparser,printer=Cmdliner.Arg.enum[("unix",`Unix);("macosx",`MacOSX);("xen",`Xen);("virtio",`Virtio);("hvt",`Hvt);("muen",`Muen);("qubes",`Qubes);("genode",`Genode);("spt",`Spt);]in(parser,printer)lettarget_serializeppf=function|`Unix->Fmt.pfppf"`Unix"|`Xen->Fmt.pfppf"`Xen"|`Virtio->Fmt.pfppf"`Virtio"|`Hvt->Fmt.pfppf"`Hvt"|`Muen->Fmt.pfppf"`Muen"|`MacOSX->Fmt.pfppf"`MacOSX"|`Qubes->Fmt.pfppf"`Qubes"|`Genode->Fmt.pfppf"`Genode"|`Spt->Fmt.pfppf"`Spt"letpp_targetfmtm=sndtarget_convfmtmletdefault_target=matchSys.getenv"MIRAGE_DEFAULT_TARGET"with|"unix"->`Unix|s->Fmt.failwith"invalid default target: %S"s|exceptionNot_found->(matchAction.run@@Action.run_cmd_outBos.Cmd.(v"uname"%"-s")with|Ok"Darwin"->`MacOSX|_->`Unix)lettarget=letdoc="Target platform to compile the unikernel for. Valid values are: $(i,xen), \
$(i,qubes), $(i,unix), $(i,macosx), $(i,virtio), $(i,hvt), $(i,spt), \
$(i,muen), $(i,genode)."inletconv=Arg.conv~conv:target_conv~runtime_conv:"target"~serialize:target_serializeinletdoc=Arg.info~docs:mirage_section~docv:"TARGET"~doc["t";"target"]~env:"MODE"inletkey=Arg.opt~stage:`Configureconvdefault_targetdocinKey.create"target"keyletis_unix=Key.match_Key.(valuetarget)@@function|#mode_unix->true|#mode_xen|#mode_solo5->falseletis_solo5=Key.match_Key.(valuetarget)@@function|#mode_solo5->true|#mode_xen|#mode_unix->falseletis_xen=Key.match_Key.(valuetarget)@@function|#mode_xen->true|#mode_solo5|#mode_unix->false(** {3 Tracing} *)lettracing_sizedefault=letdoc="The size of the trace ring buffer."inletdoc=Arg.info~docs:mirage_section~docv:"SIZE"~doc["tracing-size"]inletkey=Arg.opt~stage:`ConfigureArg.intdefaultdocinKey.create"tracing_size"key(** {2 OCaml runtime} *)letocaml_section="OCAML RUNTIME PARAMETERS"letbacktrace=letdoc="Trigger the printing of a stack backtrace when an uncaught exception \
aborts the unikernel."inletdoc=Arg.info~docs:ocaml_section~docv:"BOOL"~doc["backtrace"]inletkey=Arg.optArg.booltruedocinKey.create"backtrace"keyletrandomize_hashtables=letdoc="Turn on randomization of all hash tables by default."inletdoc=Arg.info~docs:ocaml_section~docv:"BOOL"~doc["randomize-hashtables"]inletkey=Arg.optArg.booltruedocinKey.create"randomize-hashtables"keyletallocation_policy=letdoc="The policy used for allocating in the OCaml heap. Possible values are: \
$(i,next-fit), $(i,first-fit), $(i,best-fit). Best-fit is only supported \
since OCaml 4.10."inletserializeppf=function|`Next_fit->Fmt.pfppf"`Next_fit"|`First_fit->Fmt.pfppf"`First_fit"|`Best_fit->Fmt.pfppf"`Best_fit"andconv=Mirage_runtime.Arg.allocation_policyinletconv=Arg.conv~conv~runtime_conv:"Mirage_runtime.Arg.allocation_policy"~serializeinletdoc=Arg.info~docs:ocaml_section~docv:"ALLOCATION"~doc["allocation-policy"]inletkey=Arg.optconv`Next_fitdocinKey.create"allocation-policy"keyletminor_heap_size=letdoc="The size of the minor heap (in words). Default: 256k."inletdoc=Arg.info~docs:ocaml_section~docv:"MINOR SIZE"~doc["minor-heap-size"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"minor-heap-size"keyletmajor_heap_increment=letdoc="The size increment for the major heap (in words). If less than or equal \
1000, it is a percentage of the current heap size. If more than 1000, it \
is a fixed number of words. Default: 15."inletdoc=Arg.info~docs:ocaml_section~docv:"MAJOR INCREMENT"~doc["major-heap-increment"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"major-heap-increment"keyletspace_overhead=letdoc="The percentage of live data of wasted memory, due to GC does not \
immediately collect unreachable blocks. The major GC speed is computed \
from this parameter, it will work more if smaller. Default: 80."inletdoc=Arg.info~docs:ocaml_section~docv:"SPACE OVERHEAD"~doc["space-overhead"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"space-overhead"keyletmax_space_overhead=letdoc="Heap compaction is triggered when the estimated amount of wasted memory \
exceeds this (percentage of live data). If above 1000000, compaction is \
never triggered. Default: 500."inletdoc=Arg.info~docs:ocaml_section~docv:"MAX SPACE OVERHEAD"~doc["max-space-overhead"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"max-space-overhead"keyletgc_verbosity=letdoc="GC messages on standard error output. Sum of flags. Check GC module \
documentation for details."inletdoc=Arg.info~docs:ocaml_section~docv:"VERBOSITY"~doc["gc-verbosity"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"gc-verbosity"keyletgc_window_size=letdoc="The size of the window used by the major GC for smoothing out variations \
in its workload. Between 1 adn 50, default: 1."inletdoc=Arg.info~docs:ocaml_section~docv:"WINDOW SIZE"~doc["gc-window-size"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"gc-window-size"keyletcustom_major_ratio=letdoc="Target ratio of floating garbage to major heap size for out-of-heap \
memory held by custom values. Default: 44."inletdoc=Arg.info~docs:ocaml_section~docv:"CUSTOM MAJOR RATIO"~doc["custom-major-ratio"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"custom-major-ratio"keyletcustom_minor_ratio=letdoc="Bound on floating garbage for out-of-heap memory held by custom values in \
the minor heap. Default: 100."inletdoc=Arg.info~docs:ocaml_section~docv:"CUSTOM MINOR RATIO"~doc["custom-minor-ratio"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"custom-minor-ratio"keyletcustom_minor_max_size=letdoc="Maximum amount of out-of-heap memory for each custom value allocated in \
the minor heap. Default: 8192 bytes."inletdoc=Arg.info~docs:ocaml_section~docv:"CUSTOM MINOR MAX SIZE"~doc["custom-minor-max-size"]inletkey=Arg.(opt(someint)Nonedoc)inKey.create"custom-minor-max-size"key(** {2 General mirage keys} *)letcreate_simple?(group="")?(stage=`Both)~doc~defaultconvname=letprefix=ifgroup=""thengroupelsegroup^"-"inletdoc=Arg.info~docs:unikernel_section~docv:(String.Ascii.uppercasename)~doc[prefix^name]inletkey=Arg.opt~stageconvdefaultdocinKey.create(prefix^name)key(** {3 File system keys} *)letkv_ro?group()=letconv=Cmdliner.Arg.enum[("fat",`Fat);("archive",`Archive);("crunch",`Crunch);("direct",`Direct);]inletserialize=Fmt.of_to_string@@function|`Fat->"`Fat"|`Archive->"`Archive"|`Crunch->"`Crunch"|`Direct->"`Direct"inletconv=Arg.conv~conv~serialize~runtime_conv:"kv_ro"inletdoc=Fmt.str"Use a $(i,fat), $(i,archive), $(i,crunch) or $(i,direct) pass-through \
implementation for %a."pp_groupgroupincreate_simple~doc?group~stage:`Configure~default:`Crunchconv"kv_ro"(** {3 Block device keys} *)letblock?group()=letconv=Cmdliner.Arg.enum[("xenstore",`XenstoreId);("file",`BlockFile);("ramdisk",`Ramdisk)]inletserialize=Fmt.of_to_string@@function|`XenstoreId->"`XenstoreId"|`BlockFile->"`BlockFile"|`Ramdisk->"`Ramdisk"inletconv=Arg.conv~conv~serialize~runtime_conv:"block"inletdoc=Fmt.str"Use a $(i,ramdisk), $(i,xenstore), or $(i,file) pass-through \
implementation for %a."pp_groupgroupincreate_simple~doc?group~stage:`Configure~default:`Ramdiskconv"block"(** {3 PRNG key} *)letprng=letconv=Cmdliner.Arg.enum[("stdlib",`Stdlib);("nocrypto",`Nocrypto);("fortuna",`Nocrypto)]inletserialize=Fmt.of_to_string@@function|`Stdlib->"`Stdlib"|`Nocrypto->"`Nocrypto"inletconv=Arg.conv~conv~serialize~runtime_conv:"prng"inletdoc=Fmt.str"This boot parameter is deprecated. A Fortuna PRNG \
(https://en.wikipedia.org/wiki/Fortuna_(PRNG)) will always be used. The \
mirage-crypto-entropy (https://github.com/mirage/mirage-crypto) opam \
package feeds entropy to Fortuna."increate_simple~doc~stage:`Configure~default:`Stdlibconv"prng"(** {3 Stack keys} *)letdhcp?group()=letdoc=Fmt.str"Enable dhcp for %a."pp_groupgroupincreate_simple~doc?group~stage:`Configure~default:falseArg.bool"dhcp"letnet?group():[`Socket|`Direct]optionKey.key=letconv=Cmdliner.Arg.enum[("socket",`Socket);("direct",`Direct)]inletserializefmt=function|`Socket->Fmt.stringfmt"`Socket"|`Direct->Fmt.stringfmt"`Direct"inletconv=Arg.conv~conv~runtime_conv:"net"~serializeinletdoc=Fmt.str"Use $(i,socket) or $(i,direct) group for %a."pp_groupgroupincreate_simple~doc?group~stage:`Configure~default:None(Arg.someconv)"net"(** {3 Network keys} *)letinterface?groupdefault=letdoc=Fmt.str"The network interface listened by %a."pp_groupgroupincreate_simple~doc~default?groupArg.string"interface"moduleV4=structletnetwork?groupdefault=letdoc=Fmt.str"The network of %a specified as an IP address and netmask, e.g. \
192.168.0.1/16 ."pp_groupgroupincreate_simple~doc~default?groupArg.ipv4"ipv4"letgateway?groupdefault=letdoc=Fmt.str"The gateway of %a."pp_groupgroupincreate_simple~doc~default?groupArg.(someipv4_address)"ipv4-gateway"endmoduleV6=structletnetwork?groupdefault=letdoc=Fmt.str"The network of %a specified as IPv6 address and prefix length."pp_groupgroupincreate_simple~doc~default?groupArg.(someipv6)"ipv6"letgateway?groupdefault=letdoc=Fmt.str"The gateway of %a."pp_groupgroupincreate_simple~doc~default?groupArg.(someipv6_address)"ipv6-gateway"letaccept_router_advertisements?group()=letdoc=Fmt.str"Accept router advertisements for %a."pp_groupgroupincreate_simple~doc?group~default:trueArg.bool"accept-router-advertisements"endletipv4_only?group()=letdoc=Fmt.str"Only use IPv4 for %a."pp_groupgroupincreate_simple~doc?group~default:falseArg.bool"ipv4-only"letipv6_only?group()=letdoc=Fmt.str"Only use IPv6 for %a."pp_groupgroupincreate_simple~doc?group~default:falseArg.bool"ipv6-only"letresolver?default()=letdoc=Fmt.str"DNS resolver (default to anycast.censurfridns.dk)"increate_simple~doc~defaultArg.(someip_address)"resolver"letresolver_port?(default=53)()=letdoc=Fmt.str"DNS resolver port"increate_simple~doc~defaultArg.int"resolver-port"letsyslogdefault=letdoc=Fmt.str"syslog server"increate_simple~doc~defaultArg.(someip_address)"syslog"letsyslog_portdefault=letdoc=Fmt.str"syslog server port"increate_simple~doc~defaultArg.(someint)"syslog-port"letsyslog_hostnamedefault=letdoc=Fmt.str"hostname to report to syslog"increate_simple~doc~defaultArg.string"syslog-hostname"letpp_levelppf=function|Logs.Error->Fmt.stringppf"Logs.Error"|Logs.Warning->Fmt.stringppf"Logs.Warning"|Logs.Info->Fmt.stringppf"Logs.Info"|Logs.Debug->Fmt.stringppf"Logs.Debug"|Logs.App->Fmt.stringppf"Logs.App"letpp_patternppf=function|`All->Fmt.stringppf"`All"|`Srcs->Fmt.pfppf"`Src %S"sletpp_thresholdppf(pattern,level)=Fmt.pfppf"(%a,@ %a)"pp_patternpatternpp_levellevelletlogs=letenv="MIRAGE_LOGS"inletdocs=unikernel_sectioninletconv=Cmdliner.Arg.listMirage_runtime.Arg.log_thresholdinletserializeppflevels=Fmt.(pfppf"[%a]"(list~sep:(conststring"; ")pp_threshold)levels)inletruntime_conv="(Cmdliner.Arg.list Mirage_runtime.Arg.log_threshold)"inletdoc=strf"Be more or less verbose. $(docv) must be of the form@ \
$(b,*:info,foo:debug) means that that the log threshold is set to@ \
$(b,info) for every log sources but the $(b,foo) which is set to@ \
$(b,debug)."inletlogs=Key.Arg.conv~conv~serialize~runtime_convinletinfo=Key.Arg.info~env~docv:"LEVEL"~doc~docs["l";"logs"]inletarg=Key.Arg.(optlogs[])infoinKey.create"logs"arginclude(Key:Functoria.KEYwithmoduleArg:=ArgandmoduleAlias:=Alias)