When creating a policy description, you can use the Ginger template engine that is integrated into the nk-psl-gen-c
compiler. To manage the template engine, you must use the parameters of the nk-psl-gen-c
compiler or parameters of the CMake commands build_kos_qemu_image()
and build_kos_hw_image()
.
A Ginger PSL template is a PSL file that contains syntactic constructs of the Ginger template engine in addition to declarations in PSL. Files such as security.psl.in
, security.psl
, and core.psl
are considered to be Ginger PSL templates if they contain syntactic constructs of the Ginger template engine. (A security.psl.in
file simultaneously serves as a PSL template in a different context because this file may use macros and variables that are not linked to the Ginger template engine.)
A description of the syntactic constructs of the Ginger template engine is provided in the official documentation for this template engine. For example, you can use macros.
Example of defining a macro:
{% macro VMMSafe(src) %}
match method=Allocate {
match src={{ src }} { grant () }
}
{% endmacro %}
Example macro call
{{ VMMSafe(["Einit"]) }}
This call will create the following construct:
match method=Allocate {
match src=Einit { grant () }
}
Example definition of a macro with loops:
{% macro VMMSafe(srcs) %}
{% for method in ["Allocate", "Commit", "Decommit"] %}
match method={{ method }} {
{% for src in srcs %}
match src={{ src }} { grant () }
{% endfor %}
}
{% endfor %}
{% endmacro %}
Example construct with a macro call:
match endpoint=vmm.VMM {
{{ VMMSafe(["Einit", "client.Client", "consumer.Consumer",
"kl.bc.BlobContainer", "kl.core.NameServer",
"kl.VfsEntity", "scm.Producer", "execution_manager.ExecMgrEntity",
"scm.SecurityConfigMgrEntity", "kl.drivers.ATA", "kl.drivers.PCIE"]) }}
}
When the macro is expanded in this construct, the following construct will be created:
match endpoint=vmm.VMM {
match method=Allocate {
match src = Einit { grant () }
match src=client.Client { grant () }
match src=consumer.Consumer { grant () }
match src=kl.bc.BlobContainer { grant () }
match src=kl.core.NameServer { grant () }
match src=kl.VfsEntity { grant () }
match src=scm.Producer { grant () }
match src=execution_manager.ExecMgrEntity { grant () }
match src=scm.SecurityConfigMgrEntity { grant () }
match src=kl.drivers.ATA { grant () }
match src=kl.drivers.PCIE { grant () }
}
match method=Commit {
match src = Einit { grant () }
match src=client.Client { grant () }
match src=consumer.Consumer { grant () }
match src=kl.bc.BlobContainer { grant () }
match src=kl.core.NameServer { grant () }
match src=kl.VfsEntity { grant () }
match src=scm.Producer { grant () }
match src=execution_manager.ExecMgrEntity { grant () }
match src=scm.SecurityConfigMgrEntity { grant () }
match src=kl.drivers.ATA { grant () }
match src=kl.drivers.PCIE { grant () }
}
match method=Decommit {
match src = Einit { grant () }
match src=client.Client { grant () }
match src=consumer.Consumer { grant () }
match src=kl.bc.BlobContainer { grant () }
match src=kl.core.NameServer { grant () }
match src=kl.VfsEntity { grant () }
match src=scm.Producer { grant () }
match src=execution_manager.ExecMgrEntity { grant () }
match src=scm.SecurityConfigMgrEntity { grant () }
match src=kl.drivers.ATA { grant () }
match src=kl.drivers.PCIE { grant () }
}
}
Comments can be used in Ginger PSL templates:
{# Comment that will be deleted when the template is expanded. #}
A file inclusion construct can also be used in Ginger PSL templates.
Example of a file inclusion construct:
{% include "defs.ginger" %}
The defs.ginger
file may contain definitions of macros used in a Ginger PSL template, for example. This file must be located in the same directory as the Ginger PSL template that contains this construct.