From ccc1833eda5c99a8e7ff03ebfff9cee9c54e1134 Mon Sep 17 00:00:00 2001 From: AtomicFS Date: Mon, 15 Apr 2024 17:04:22 +0200 Subject: [PATCH] docs: add more docs Signed-off-by: AtomicFS --- docs/book.toml | 7 +- docs/src/SUMMARY.md | 19 +- docs/src/firmware-action/config.md | 63 ++-- docs/src/firmware-action/features.md | 6 + .../firmware-action/get_started/01_repo.md | 38 ++ .../get_started/02_coreboot_config.md | 12 + .../get_started/03_json_config.md | 26 ++ .../get_started/04_get_firmware_action.md | 4 + .../get_started/05_run_firmware_action.md | 18 + .../get_started/06_run_in_ci.md | 14 + .../get_started/get_started.md | 18 + docs/src/firmware-action/usage.md | 2 +- docs/src/firmware-action/usage_github.md | 58 ++- docs/src/firmware-action/usage_local.md | 39 +- docs/theme/index.hbs | 346 ++++++++++++++++++ docs/theme/pagetoc.css | 57 +++ docs/theme/pagetoc.js | 49 +++ 17 files changed, 736 insertions(+), 40 deletions(-) create mode 100644 docs/src/firmware-action/features.md create mode 100644 docs/src/firmware-action/get_started/01_repo.md create mode 100644 docs/src/firmware-action/get_started/02_coreboot_config.md create mode 100644 docs/src/firmware-action/get_started/03_json_config.md create mode 100644 docs/src/firmware-action/get_started/04_get_firmware_action.md create mode 100644 docs/src/firmware-action/get_started/05_run_firmware_action.md create mode 100644 docs/src/firmware-action/get_started/06_run_in_ci.md create mode 100644 docs/src/firmware-action/get_started/get_started.md create mode 100644 docs/theme/index.hbs create mode 100644 docs/theme/pagetoc.css create mode 100644 docs/theme/pagetoc.js diff --git a/docs/book.toml b/docs/book.toml index a779d973..23afc9b5 100644 --- a/docs/book.toml +++ b/docs/book.toml @@ -18,11 +18,12 @@ preferred-dark-theme = "navy" git-repository-url = "https://github.com/9elements/firmware-action" git-repository-icon = "fa-git" # icons: https://fontawesome.com/v4/icons/ -additional-css = ["./mdbook-admonish.css"] +additional-css = ["mdbook-admonish.css", "theme/pagetoc.css", "./mdbook-admonish.css"] +additional-js = ["theme/pagetoc.js"] [output.html.fold] enable = true -level = 1 +level = 2 [preprocessor.template] @@ -33,3 +34,5 @@ assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install` [preprocessor.footnote] +[preprocessor.pagetoc] + diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 04d9cb43..1d750e1f 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -7,13 +7,22 @@ --- - [firmware-action]() - - [Configuration](firmware-action/config.md) - - [Usage](firmware-action/usage.md) - - [local system](firmware-action/usage_local.md) + - [Get started](firmware-action/get_started/get_started.md) + - [Repository](firmware-action/get_started/01_repo.md) + - [coreboot configuration](firmware-action/get_started/02_coreboot_config.md) + - [JSON configuration](firmware-action/get_started/03_json_config.md) + - [Get firmware-action](firmware-action/get_started/04_get_firmware_action.md) + - [Run firmware-action locally](firmware-action/get_started/05_run_firmware_action.md) + - [Run firmware-action in CI](firmware-action/get_started/06_run_in_ci.md) + - [TLDR; Usage](firmware-action/usage.md) + - [Local system](firmware-action/usage_local.md) - [GitHub CI](firmware-action/usage_github.md) + - [Configuration](firmware-action/config.md) + - [Features](firmware-action/features.md) --- -- [Docker containers](docker/docker.md) - - [Docker compose](docker/docker-compose.md) +- [For firmware-action developers]() + - [Docker containers](docker/docker.md) + - [Docker compose](docker/docker-compose.md) diff --git a/docs/src/firmware-action/config.md b/docs/src/firmware-action/config.md index e499251f..7b7fa794 100644 --- a/docs/src/firmware-action/config.md +++ b/docs/src/firmware-action/config.md @@ -1,13 +1,14 @@ # Configuration -```admonish example -Example of JSON configuration file: +```admonish example collapsible=true title="Example of JSON configuration file" ~~~json {{#include ../../../tests/example_config.json}} ~~~ ``` -The config are split by type (coreboot, linux or edk2). In each category can be any number of modules. +The config are split by type (`coreboot`, `linux`, `edk2`, ...). + +In each type can be any number of modules. Each module has a name, which can be anything as long as it is unique (unique string across all modules of all types). In the example above there are 3 modules (`coreboot-example`, `linux-example`, `edk2-example`). @@ -15,14 +16,23 @@ The configuration above can be simplified to this: ``` / ├── coreboot/ -│   └── coreboot_example -├── linux/ -│   └── linux_example -└── edk2/ -   └── edk2_example +│   └── coreboot-example +├── edk2/ +│   └── edk2-example +├── firmware_stitching/ +│  └── stitching-example +└── linux/ +    └── linux-example ``` -You can have multiple modules, as long as names are unique: +Not all types must be present or defined. If you are building coreboot and coreboot only, you can have only coreboot present. +``` +/ +└── coreboot/ +   └── coreboot_example +``` + +You can have multiple modules of each type, as long as their names are unique. ``` / ├── coreboot/ @@ -51,7 +61,7 @@ Each module has sections: {{#include ../../../action/recipes/coreboot.go:CorebootOpts}} ``` -`common` and `specific` are identical in function. There is no real difference between these two. They are split to simplify the code. +`common` & `specific` are identical in function. There is no real difference between these two. They are split to simplify the code. They define things like path to source code, version and source of SDK to use, and so on. `depends` on the other hand allows you to specify dependency (or relation) between modules. For example your `coreboot` uses `edk2` as payload. So you can specify this dependency by listing name of the `edk2` module in `depends` of your `coreboot` module. @@ -60,23 +70,13 @@ Each module has sections: "coreboot": { "coreboot-example": { "depends": ["edk2-example"], - "common": { - ... - }, - "specific": { - ... - } + ... } }, "edk2": { "edk2-example": { "depends": null, - "common": { - ... - }, - "specific": { - ... - } + ... } } } @@ -86,10 +86,10 @@ With such configuration, you can then run `firmware-action` recursively, and it ``` ./firmware-action build --config=./my-config.json --target=coreboot-example --recursive ``` -In this case `firmware-action` would build `edk2-example` and then `coreboot-example`. +In this case `firmware-action` would build `edk2-example` first and then `coreboot-example`. ```admonish tip -By changing inputs and outputs, you can then feed output of one module into inputs of another module. +By changing inputs and outputs, you can then feed output of one module into input of another module. This way you can build the entire firmware stack in single step. ``` @@ -97,10 +97,10 @@ This way you can build the entire firmware stack in single step. ## Common and Specific -To explain each and every entry in the configuration, here are snippets of the code with comments. +To explain each and every entry in the configuration, here are snippets of the source code with comments. ```admonish info -In the code below, the tag `json` (for example `:"sdk_url"`) specifies what the field is called in JSON file. +In the code below, the tag `json` (for example `json:"sdk_url"`) specifies what the field is called in JSON file. Tag `validate:"required"`, it means that the field is required and must not be empty. Empty required field will fail validation and terminate program with error. @@ -116,18 +116,27 @@ For more tails see [go-playground/validator](https://github.com/go-playground/va {{#include ../../../action/recipes/config.go:CommonOpts}} ``` -### Specific / Coreboot +### Specific / coreboot ```go +{{#include ../../../action/recipes/coreboot.go:CorebootOpts}} {{#include ../../../action/recipes/coreboot.go:CorebootBlobs}} ``` ### Specific / Linux ```go +{{#include ../../../action/recipes/linux.go:LinuxOpts}} {{#include ../../../action/recipes/linux.go:LinuxSpecific}} ``` ### Specific / Edk2 ```go +{{#include ../../../action/recipes/edk2.go:Edk2Opts}} {{#include ../../../action/recipes/edk2.go:Edk2Specific}} ``` +### Specific / Firmware stitching +```go +{{#include ../../../action/recipes/stitching.go:FirmwareStitchingOpts}} +{{#include ../../../action/recipes/stitching.go:IfdtoolEntry}} +``` + diff --git a/docs/src/firmware-action/features.md b/docs/src/firmware-action/features.md new file mode 100644 index 00000000..ab6ca147 --- /dev/null +++ b/docs/src/firmware-action/features.md @@ -0,0 +1,6 @@ +# Features + +- [Environment variables in JSON configuration](./usage_github.md#parametric-builds-with-environment-variables) +- [Recursive builds](./config.md#modules) +- Interactive mode + diff --git a/docs/src/firmware-action/get_started/01_repo.md b/docs/src/firmware-action/get_started/01_repo.md new file mode 100644 index 00000000..2cd48ce2 --- /dev/null +++ b/docs/src/firmware-action/get_started/01_repo.md @@ -0,0 +1,38 @@ +# Start a new git repository + +Start a new repository in GitHub and the clone it. + + +## Add coreboot as submodule + +~~~admonish tip +Add git submodule with: +``` +git submodule add +``` +~~~ + +Add [coreboot repository](https://review.coreboot.org/admin/repos/coreboot,general) as a submodule: +```bash +git submodule add --depth=1 "https://review.coreboot.org/coreboot" coreboot +``` + +```bash +git submodule update --init +``` + +Optionally checkout a release tag, for example `4.19` (it is a bit older release from January 2023, but should suffice for demonstration) +```bash +( cd coreboot; git fetch origin tag "4.19"; git checkout "4.19" ) +``` + +Recursively initialize submodules. + +```bash +git submodule update --init --recursive +``` + +~~~admonish warning +Recursively initializing all submodules in coreboot will take a moment. +~~~ + diff --git a/docs/src/firmware-action/get_started/02_coreboot_config.md b/docs/src/firmware-action/get_started/02_coreboot_config.md new file mode 100644 index 00000000..ffde2e56 --- /dev/null +++ b/docs/src/firmware-action/get_started/02_coreboot_config.md @@ -0,0 +1,12 @@ +## Create a coreboot configuration file + +Now we need to create a configuration file for coreboot. + +Either follow a [coreboot guide](https://doc.coreboot.org/tutorial/part1.html#step-5-configure-the-build) to get a base-bones-basic configuration, or just copy-paste this text into `seabios_defconfig` file. + +~~~admonish example title="seabios_defconfig" +```properties +{{#include ../../firmware-action-example/seabios_defconfig}} +``` +~~~ + diff --git a/docs/src/firmware-action/get_started/03_json_config.md b/docs/src/firmware-action/get_started/03_json_config.md new file mode 100644 index 00000000..6b39b150 --- /dev/null +++ b/docs/src/firmware-action/get_started/03_json_config.md @@ -0,0 +1,26 @@ +# Create a JSON configuration file + +This configuration file is for firmware-action, so that it knows what to do and where to find things. Let's call it `firmware-action.json`. + +~~~admonish example title="firmware-action.json" +```json +{{#include ../../firmware-action-example/firmware-action.json}} +``` +~~~ + +~~~admonish info +Field `repo_path` is pointing to the location of our coreboot submodule. +~~~ + +~~~admonish info +Field `defconfig_path` is pointing to the location of coreboot's configuration file. +~~~ + +~~~admonish info +Firmware action can be used to compile other firmware too, and even combine multiple firmware projects (to a certain degree). + +For this reason the JSON configuration file is divided into categories (`coreboot`, `edk2`, etc). Each category can contain multiple entries. + +Entries can depend on each other, which allows you to combine them - you can have for example `coreboot` firmware with `edk2` payload. +~~~ + diff --git a/docs/src/firmware-action/get_started/04_get_firmware_action.md b/docs/src/firmware-action/get_started/04_get_firmware_action.md new file mode 100644 index 00000000..52ff40df --- /dev/null +++ b/docs/src/firmware-action/get_started/04_get_firmware_action.md @@ -0,0 +1,4 @@ +# Get firmware-action + +Either [clone the repository and build the executable yourself](../usage_local.md), or just download pre-compiled executable from [releases](https://github.com/9elements/firmware-action/releases). + diff --git a/docs/src/firmware-action/get_started/05_run_firmware_action.md b/docs/src/firmware-action/get_started/05_run_firmware_action.md new file mode 100644 index 00000000..2f99ee2a --- /dev/null +++ b/docs/src/firmware-action/get_started/05_run_firmware_action.md @@ -0,0 +1,18 @@ +# Run firmware-action locally + +```bash +./firmware-action build --config=firmware-action.json --target=coreboot-example +``` + +`firmware-action` will firstly download `registry.dagger.io/engine` container needed for dagger and start it. + +Then it will proceed to download `coreboot` container (specified by `sdk_url` in JSON config), copy into it specified files and then start compilation. + +If compilation is successful, a new directory `output-coreboot/` will be created (as specified by `output_dir` in JSON config) which will contain files (specified by `container_output_files` in JSON config) and possibly also directories (specified by `container_output_dirs` in JSON config). + +~~~admonish info +`container_output_dirs` and `container_output_files` are lists of directories and files to be extracted from the container once compilation finished successfully. + +These are then placed into `output_dir`. +~~~ + diff --git a/docs/src/firmware-action/get_started/06_run_in_ci.md b/docs/src/firmware-action/get_started/06_run_in_ci.md new file mode 100644 index 00000000..a15ee8f2 --- /dev/null +++ b/docs/src/firmware-action/get_started/06_run_in_ci.md @@ -0,0 +1,14 @@ +## Run firmware-action in GitHub CI + +Now that we have `firmware-action` working on local system. Let's set up CI. + +~~~admonish example title=".github/workflows/example.yml" +```yaml +{{#include ../../firmware-action-example/.github/workflows/example.yml}} +``` +~~~ + +Commit, push and watch. And that is it. + +Now you should be able to build coreboot in CI and on your local machine. + diff --git a/docs/src/firmware-action/get_started/get_started.md b/docs/src/firmware-action/get_started/get_started.md new file mode 100644 index 00000000..b379fbf3 --- /dev/null +++ b/docs/src/firmware-action/get_started/get_started.md @@ -0,0 +1,18 @@ +# Get started + +This guide will provide instructions step by step on how to get started with firmware-action, and it will demonstrate the use on [coreboot](https://coreboot.org/) example. + +In this guide we will: +- start a new repository + - in this guide it will be hosted in [GitHub](https://github.com/) +- we will build a simple coreboot for [QEMU](https://wiki.archlinux.org/title/QEMU) +- we will be able to build coreboot in GitHub action and locally + +The code from this example is available in [firmware-action-example](https://github.com/9elements/firmware-action-example). + + +## Prerequisites + +- installed [Docker](https://wiki.archlinux.org/title/Docker) +- installed git + diff --git a/docs/src/firmware-action/usage.md b/docs/src/firmware-action/usage.md index 25faa20c..33376645 100644 --- a/docs/src/firmware-action/usage.md +++ b/docs/src/firmware-action/usage.md @@ -1,4 +1,4 @@ -# Usage +# TLDR; Usage `firmware-action` was created with the intention to unify building of firmware across environments. diff --git a/docs/src/firmware-action/usage_github.md b/docs/src/firmware-action/usage_github.md index d01d41d4..e9b47bd5 100644 --- a/docs/src/firmware-action/usage_github.md +++ b/docs/src/firmware-action/usage_github.md @@ -18,7 +18,10 @@ jobs: ~~~ ``` -To take advantage of matrix builds, it is possible to use environment variables inside the JSON configuration file. + +## Parametric builds with environment variables + +To take advantage of matrix builds in GitHub, it is possible to use environment variables inside the JSON configuration file. ```admonish example For example let's make `COREBOOT_VERSION` environment variable which will hold version of coreboot. @@ -53,3 +56,56 @@ jobs: ~~~ ``` + +## Examples + +In our repository we have multiple examples (even though rather simple ones) defined in [.github/workflows/example.yml](https://github.com/9elements/firmware-action/blob/main/.github/workflows/example.yml). + +```admonish example collapsible=true title="Coreboot" +`.github/workflows/example.yml`: +~~~yaml +{{#include ../../../.github/workflows/example.yml:example_build_coreboot}} +~~~ + +`tests/example_config__coreboot.json`: +~~~json +{{#include ../../../tests/example_config__coreboot.json}} +~~~ +``` + +```admonish example collapsible=true title="Linux Kernel" +`.github/workflows/example.yml`: +~~~yaml +{{#include ../../../.github/workflows/example.yml:example_build_linux_kernel}} +~~~ + +`tests/example_config__linux.json`: +~~~json +{{#include ../../../tests/example_config__linux.json}} +~~~ +``` + +```admonish example collapsible=true title="Edk2" +`.github/workflows/example.yml`: +~~~yaml +{{#include ../../../.github/workflows/example.yml:example_build_edk2}} +~~~ + +`tests/example_config__edk2.json`: +~~~json +{{#include ../../../tests/example_config__edk2.json}} +~~~ +``` + +```admonish example collapsible=true title="Firmware Stitching" +`.github/workflows/example.yml`: +~~~yaml +{{#include ../../../.github/workflows/example.yml:example_build_stitch}} +~~~ + +`tests/example_config__firmware_stitching.json`: +~~~json +{{#include ../../../tests/example_config__firmware_stitching.json}} +~~~ +``` + diff --git a/docs/src/firmware-action/usage_local.md b/docs/src/firmware-action/usage_local.md index b2776733..092e19b5 100644 --- a/docs/src/firmware-action/usage_local.md +++ b/docs/src/firmware-action/usage_local.md @@ -1,18 +1,49 @@ # Local system To get firmware-action, there are few options: -- [firmware-action](https://aur.archlinux.org/packages/firmware-action) Arch Linux AUR package +- download compiled binary executable from [releases](https://github.com/9elements/firmware-action/releases) - build from source with [taskfile](https://taskfile.dev/) +- `firmware-action` [Arch Linux AUR package](https://aur.archlinux.org/packages/firmware-action) -To build from source: + +## Build from source ``` git clone https://github.com/9elements/firmware-action.git cd firmware-action task build-go-binary ``` -To run: + +## Run +``` +./firmware-action build --config= --target= +``` + + +## Help + ``` -./firmware-action build --config=./firmware-action-config.json --target=my-target +Usage: firmware-action --config="firmware-action.json" [flags] + +Utility to create firmware images for several open source firmware solutions + +Flags: + -h, --help Show context-sensitive help. + --json switch to JSON stdout and stderr output + --indent enable indentation for JSON output + --debug increase verbosity + --config="firmware-action.json" Path to configuration file + +Commands: + build --config="firmware-action.json" --target=STRING [flags] + Build a target defined in configuration file + + generate-config --config="firmware-action.json" [flags] + Generate empty configuration file + + version --config="firmware-action.json" [flags] + Print version and exit + +Run "firmware-action --help" for more information on a command. ``` diff --git a/docs/theme/index.hbs b/docs/theme/index.hbs new file mode 100644 index 00000000..062d73a4 --- /dev/null +++ b/docs/theme/index.hbs @@ -0,0 +1,346 @@ + + + + + + {{ title }} + {{#if is_print }} + + {{/if}} + {{#if base_url}} + + {{/if}} + + + + {{> head}} + + + + + + {{#if favicon_svg}} + + {{/if}} + {{#if favicon_png}} + + {{/if}} + + + + {{#if print_enable}} + + {{/if}} + + + + {{#if copy_fonts}} + + {{/if}} + + + + + + + + {{#each additional_css}} + + {{/each}} + + {{#if mathjax_support}} + + + {{/if}} + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ {{> header}} + + + + {{#if search_enabled}} + + {{/if}} + + + + +
+
+ {{{ content }}} +
+ + +
+
+ + + +
+ + {{#if live_reload_endpoint}} + + + {{/if}} + + {{#if google_analytics}} + + + {{/if}} + + {{#if playground_line_numbers}} + + {{/if}} + + {{#if playground_copyable}} + + {{/if}} + + {{#if playground_js}} + + + + + + {{/if}} + + {{#if search_js}} + + + + {{/if}} + + + + + + + {{#each additional_js}} + + {{/each}} + + {{#if is_print}} + {{#if mathjax_support}} + + {{else}} + + {{/if}} + {{/if}} + +
+ + diff --git a/docs/theme/pagetoc.css b/docs/theme/pagetoc.css new file mode 100644 index 00000000..8412a45d --- /dev/null +++ b/docs/theme/pagetoc.css @@ -0,0 +1,57 @@ +@media only screen and (max-width:1439px) { + .sidetoc { + display: none; + } +} + +@media only screen and (min-width:1440px) { + main { + position: relative; + } + .sidetoc { + margin-left: auto; + margin-right: auto; + left: calc(100% + (var(--content-max-width))/4 - 140px); + position: absolute; + } + .pagetoc { + position: fixed; + width: 200px; + height: calc(100vh - var(--menu-bar-height) - 0.67em * 4); + overflow: auto; + } + .pagetoc a { + border-left: 1px solid var(--sidebar-bg); + color: var(--fg) !important; + display: block; + padding-bottom: 5px; + padding-top: 5px; + padding-left: 10px; + text-align: left; + text-decoration: none; + } + .pagetoc a:hover, + .pagetoc a.active { + background: var(--sidebar-bg); + color: var(--sidebar-fg) !important; + } + .pagetoc .active { + background: var(--sidebar-bg); + color: var(--sidebar-fg); + } + .pagetoc .pagetoc-H2 { + padding-left: 20px; + } + .pagetoc .pagetoc-H3 { + padding-left: 40px; + } + .pagetoc .pagetoc-H4 { + padding-left: 60px; + } + .pagetoc .pagetoc-H5 { + display: none; + } + .pagetoc .pagetoc-H6 { + display: none; + } +} diff --git a/docs/theme/pagetoc.js b/docs/theme/pagetoc.js new file mode 100644 index 00000000..49e0bf97 --- /dev/null +++ b/docs/theme/pagetoc.js @@ -0,0 +1,49 @@ +// Un-active everything when you click it +Array.prototype.forEach.call(document.getElementsByClassName("pagetoc")[0].children, function(el) { + el.addEventHandler("click", function() { + Array.prototype.forEach.call(document.getElementsByClassName("pagetoc")[0].children, function(el) { + el.classList.remove("active"); + }); + el.classList.add("active"); + }); +}); + +var updateFunction = function() { + + var id; + var elements = document.getElementsByClassName("header"); + Array.prototype.forEach.call(elements, function(el) { + if (window.pageYOffset >= el.offsetTop) { + id = el; + } + }); + + Array.prototype.forEach.call(document.getElementsByClassName("pagetoc")[0].children, function(el) { + el.classList.remove("active"); + }); + if (!id) return; + Array.prototype.forEach.call(document.getElementsByClassName("pagetoc")[0].children, function(el) { + if (id.href.localeCompare(el.href) == 0) { + el.classList.add("active"); + } + }); +}; + +// Populate sidebar on load +window.addEventListener('load', function() { + var pagetoc = document.getElementsByClassName("pagetoc")[0]; + var elements = document.getElementsByClassName("header"); + Array.prototype.forEach.call(elements, function (el) { + var link = document.createElement("a"); + link.appendChild(document.createTextNode(el.text)); + link.href = el.href; + link.classList.add("pagetoc-" + el.parentElement.tagName); + pagetoc.appendChild(link); + }); + updateFunction.call(); +}); + + + +// Handle active elements on scroll +window.addEventListener("scroll", updateFunction);