aboutsummaryrefslogtreecommitdiffstats
path: root/docs/getting_started_build_tools.md
blob: fea20e59b4dd011869398bdc567979197b3a3b6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# Installing Build Tools

This page describes setting up the build environment for QMK. These instructions cover AVR processors (such as the atmega32u4).

<!-- FIXME: We should have ARM instructions somewhere. -->

**Note:** If this is your first time here, check out the [Complete Newbs Guide](newbs.md) page.

Before continuing, double check that your submodules (third-party libraries) are up to date by running `make git-submodule`.

## Linux

To ensure you are always up to date, you can just run `sudo util/qmk_install.sh`. That should always install all the dependencies needed. **This will run `apt-get upgrade`.**

You can also install things manually, but this documentation might not be always up to date with all requirements.

The current requirements are the following, but not all might be needed depending on what you do. Also note that some systems might not have all the dependencies available as packages, or they might be named differently.

```
build-essential
gcc
unzip
wget
zip
gcc-avr
binutils-avr
avr-libc
dfu-programmer
dfu-util
gcc-arm-none-eabi
binutils-arm-none-eabi
libnewlib-arm-none-eabi
git
```

Install the dependencies with your favorite package manager.

Debian / Ubuntu example:

    sudo apt-get update
    sudo apt-get install gcc unzip wget zip gcc-avr binutils-avr avr-libc dfu-programmer dfu-util gcc-arm-none-eabi binutils-arm-none-eabi libnewlib-arm-none-eabi

Fedora / Red Hat example:

    sudo dnf install gcc unzip wget zip dfu-util dfu-programmer avr-gcc avr-libc binutils-avr32-linux-gnu arm-none-eabi-gcc-cs arm-none-eabi-binutils-cs arm-none-eabi-newlib

Arch / Manjaro example:

    pacman -S base-devel gcc unzip wget zip avr-gcc avr-binutils avr-libc dfu-util arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib git dfu-programmer dfu-util

## Nix

If you're on [NixOS](https://nixos.org/), or have Nix installed on Linux or macOS, run `nix-shell` from the repository root to get a build environment.

By default, this will download compilers for both AVR and ARM. If you don't need both, disable the `avr` or `arm` arguments, e.g.:

    nix-shell --arg arm false

## macOS
If you're using [Homebrew](http://brew.sh/), you can use the following commands:

    brew tap osx-cross/avr
    brew tap osx-cross/arm
    brew update
    brew install avr-gcc@8
    brew link --force avr-gcc@8
    brew install dfu-programmer
    brew install dfu-util
    brew install arm-gcc-bin@8
    brew link --force arm-gcc-bin@8
    brew install avrdude

This is the recommended method. If you don't have homebrew, [install it!](http://brew.sh/) It's very much worth it for anyone who works in the command line. Note that the `make` and `make install` portion during the homebrew installation of `avr-gcc@8` can take over 20 minutes and exhibit high CPU usage.

## Windows with msys2 (recommended)

The best environment to use, for Windows Vista through any later version (tested on 7 and 10), is [msys2](http://www.msys2.org).

* Install msys2 by downloading it and following the instructions here: http://www.msys2.org
* Open the ``MSYS2 MingGW 64-bit`` shortcut
* Navigate to your QMK repository. For example, if it's in the root of your c drive:
 * `$ cd /c/qmk_firmware`
* Run `util/qmk_install.sh` and follow the prompts

## Windows 10 (deprecated)
These are the old instructions for Windows 10. We recommend you use [MSYS2 as outlined above](#windows-with-msys2-recommended).

### Creators Update
If you have Windows 10 with Creators Update or later, you can build and flash the firmware directly. Before the Creators Update, only building was possible. If you don't have it yet or if are unsure, follow [these instructions](https://support.microsoft.com/en-us/instantanswers/d4efb316-79f0-1aa1-9ef3-dcada78f3fa0/get-the-windows-10-creators-update).

### Windows Subsystem for Linux
In addition to the Creators Update, you need Windows 10 Subystem for Linux, so install it following [these instructions](http://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/). If you already have the Windows 10 Subsystem for Linux from the Anniversary update it's recommended that you [upgrade](https://betanews.com/2017/04/14/upgrade-windows-subsystem-for-linux/) it to 16.04LTS, because some keyboards don't compile with the toolchains included in 14.04LTS. Note that you need to know what your are doing if you chose the `sudo do-release-upgrade` method.

### Git
If you already have cloned the repository on your Windows file system you can ignore this section.

You will need to clone the repository to your Windows file system using the normal Git for Windows and **not** the WSL Git. So if you haven't installed Git before, [download](https://git-scm.com/download/win) and install it. Then [set it up](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup), it's important that you setup the e-mail and user name, especially if you are planning to contribute.

Once Git is installed, open the Git Bash command and change the directory to where you want to clone QMK; note that you have to use forward slashes, and that your c drive is accessed like this `/c/path/to/where/you/want/to/go`. Then run `git clone --recurse-submodules https://github.com/qmk/qmk_firmware`, this will create a new folder `qmk_firmware` as a subfolder of the current one.

### Toolchain Setup
The Toolchain setup is done through the Windows Subsystem for Linux, and the process is fully automated. If you want to do everything manually, there are no other instructions than the scripts themselves, but you can always open issues and ask for more information.

1. Open "Bash On Ubuntu On Windows" from the start menu.
2. Go to the directory where you cloned `qmk_firmware`. Note that the paths start with `/mnt/` in the WSL, so you have to write for example `cd /mnt/c/path/to/qmk_firmware`.
3. Run `util/wsl_install.sh` and follow the on-screen instructions.
4. Close the Bash command window, and re-open it.
5. You are ready to compile and flash the firmware!

### Some Important Things to Keep in Mind
* You can run `util/wsl_install.sh` again to get all the newest updates.
* Your QMK repository need to be on a Windows file system path, since WSL can't run executables outside it.
* The WSL Git is **not** compatible with the Windows Git, so use the Windows Git Bash or a windows Git GUI for all Git operations
* You can edit files either inside WSL or normally using Windows, but note that if you edit makefiles or shell scripts, make sure you are using an editor that saves the files with Unix line endings. Otherwise the compilation might not work.

## Docker

If this is a bit complex for you, Docker might be the turnkey solution you need. After installing [Docker CE](https://docs.docker.com/install/#supported-platforms), run the following command from the `qmk_firmware` directory to build a keyboard/keymap:
```bash
util/docker_build.sh keyboard:keymap
# For example: util/docker_build.sh ergodox_ez:steno
```
This will compile the desired keyboard/keymap and leave the resulting `.hex` or `.bin` file in the QMK directory for you to flash. If `:keymap` is omitted, all keymaps are used. Note that the parameter format is the same as when building with `make`.

You can also start the script without any parameters, in which case it will ask you to input the build parameters one by one, which you may find easier to use:
```bash
util/docker_build.sh
# Reads parameters as input (leave blank for all keyboards/keymaps)
```

There is also support for building _and_ flashing the keyboard straight from Docker by specifying the `target` as well:
```bash
util/docker_build.sh keyboard:keymap:target
# For example: util/docker_build.sh planck/rev6:default:flash
```
If you're on Linux, this should work out of the box. On Windows and macOS, it requires [Docker Machine](http://gw.tnode.com/docker/docker-machine-with-usb-support-on-windows-macos/) to be running. This is tedious to set up, so it's not recommended; use [QMK Toolbox](https://github.com/qmk/qmk_toolbox) instead.

!> Docker for Windows requires [Hyper-V](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v) to be enabled. This means that it cannot work on versions of Windows which don't have Hyper-V, such as Windows 7, Windows 8 and **Windows 10 Home**.

## Vagrant
If you have any problems building the firmware, you can try using a tool called Vagrant. It will set up a virtual computer with a known configuration that's ready-to-go for firmware building. OLKB does NOT host the files for this virtual computer. Details on how to set up Vagrant are in the [vagrant guide](getting_started_vagrant.md).
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
/*
 * Copyright (c) 2006-2007, XenSource Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */


#include <stddef.h>
#include <stdlib.h>

#include "xen_common.h"
#include "xen_host.h"
#include "xen_host_cpu.h"
#include "xen_host_metrics.h"
#include "xen_internal.h"
#include "xen_pbd.h"
#include "xen_pif.h"
#include "xen_sr.h"
#include "xen_string_string_map.h"
#include "xen_vm.h"


XEN_FREE(xen_host)
XEN_SET_ALLOC_FREE(xen_host)
XEN_ALLOC(xen_host_record)
XEN_SET_ALLOC_FREE(xen_host_record)
XEN_ALLOC(xen_host_record_opt)
XEN_RECORD_OPT_FREE(xen_host)
XEN_SET_ALLOC_FREE(xen_host_record_opt)


static const struct_member xen_host_record_struct_members[] =
    {
        { .key = "uuid",
          .type = &abstract_type_string,
          .offset = offsetof(xen_host_record, uuid) },
        { .key = "name_label",
          .type = &abstract_type_string,
          .offset = offsetof(xen_host_record, name_label) },
        { .key = "name_description",
          .type = &abstract_type_string,
          .offset = offsetof(xen_host_record, name_description) },
        { .key = "API_version_major",
          .type = &abstract_type_int,
          .offset = offsetof(xen_host_record, api_version_major) },
        { .key = "API_version_minor",
          .type = &abstract_type_int,
          .offset = offsetof(xen_host_record, api_version_minor) },
        { .key = "API_version_vendor",
          .type = &abstract_type_string,
          .offset = offsetof(xen_host_record, api_version_vendor) },
        { .key = "API_version_vendor_implementation",
          .type = &abstract_type_string_string_map,
          .offset = offsetof(xen_host_record, api_version_vendor_implementation) },
        { .key = "software_version",
          .type = &abstract_type_string_string_map,
          .offset = offsetof(xen_host_record, software_version) },
        { .key = "other_config",
          .type = &abstract_type_string_string_map,
          .offset = offsetof(xen_host_record, other_config) },
        { .key = "capabilities",
          .type = &abstract_type_string_set,
          .offset = offsetof(xen_host_record, capabilities) },
        { .key = "supported_bootloaders",
          .type = &abstract_type_string_set,
          .offset = offsetof(xen_host_record, supported_bootloaders) },
        { .key = "resident_VMs",
          .type = &abstract_type_ref_set,
          .offset = offsetof(xen_host_record, resident_vms) },
        { .key = "logging",
          .type = &abstract_type_string_string_map,
          .offset = offsetof(xen_host_record, logging) },
        { .key = "PIFs",
          .type = &abstract_type_ref_set,
          .offset = offsetof(xen_host_record, pifs) },
        { .key = "suspend_image_sr",
          .type = &abstract_type_ref,
          .offset = offsetof(xen_host_record, suspend_image_sr) },
        { .key = "crash_dump_sr",
          .type = &abstract_type_ref,
          .offset = offsetof(xen_host_record, crash_dump_sr) },
        { .key = "PBDs",
          .type = &abstract_type_ref_set,
          .offset = offsetof(xen_host_record, pbds) },
        { .key = "host_CPUs",
          .type = &abstract_type_ref_set,
          .offset = offsetof(xen_host_record, host_cpus) },
        { .key = "metrics",
          .type = &abstract_type_ref,
          .offset = offsetof(xen_host_record, metrics) }
    };

const abstract_type xen_host_record_abstract_type_ =
    {
       .typename = STRUCT,
       .struct_size = sizeof(xen_host_record),
       .member_count =
           sizeof(xen_host_record_struct_members) / sizeof(struct_member),
       .members = xen_host_record_struct_members
    };


void
xen_host_record_free(xen_host_record *record)
{
    if (record == NULL)
    {
        return;
    }
    free(record->handle);
    free(record->uuid);
    free(record->name_label);
    free(record->name_description);
    free(record->api_version_vendor);
    xen_string_string_map_free(record->api_version_vendor_implementation);
    xen_string_string_map_free(record->software_version);
    xen_string_string_map_free(record->other_config);
    xen_string_set_free(record->capabilities);
    xen_string_set_free(record->supported_bootloaders);
    xen_vm_record_opt_set_free(record->resident_vms);
    xen_string_string_map_free(record->logging);
    xen_pif_record_opt_set_free(record->pifs);
    xen_sr_record_opt_free(record->suspend_image_sr);
    xen_sr_record_opt_free(record->crash_dump_sr);
    xen_pbd_record_opt_set_free(record->pbds);
    xen_host_cpu_record_opt_set_free(record->host_cpus);
    xen_host_metrics_record_opt_free(record->metrics);
    free(record);
}


bool
xen_host_get_record(xen_session *session, xen_host_record **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = xen_host_record_abstract_type_;

    *result = NULL;
    XEN_CALL_("host.get_record");

    if (session->ok)
    {
       (*result)->handle = xen_strdup_((*result)->uuid);
    }

    return session->ok;
}


bool
xen_host_get_by_uuid(xen_session *session, xen_host *result, char *uuid)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = uuid }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_by_uuid");
    return session->ok;
}


bool
xen_host_get_by_name_label(xen_session *session, struct xen_host_set **result, char *label)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = label }
        };

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    XEN_CALL_("host.get_by_name_label");
    return session->ok;
}


bool
xen_host_get_name_label(xen_session *session, char **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_name_label");
    return session->ok;
}


bool
xen_host_get_name_description(xen_session *session, char **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_name_description");
    return session->ok;
}


bool
xen_host_get_api_version_major(xen_session *session, int64_t *result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_int;

    XEN_CALL_("host.get_API_version_major");
    return session->ok;
}


bool
xen_host_get_api_version_minor(xen_session *session, int64_t *result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_int;

    XEN_CALL_("host.get_API_version_minor");
    return session->ok;
}


bool
xen_host_get_api_version_vendor(xen_session *session, char **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_API_version_vendor");
    return session->ok;
}


bool
xen_host_get_api_version_vendor_implementation(xen_session *session, xen_string_string_map **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_string_map;

    *result = NULL;
    XEN_CALL_("host.get_API_version_vendor_implementation");
    return session->ok;
}


bool
xen_host_get_software_version(xen_session *session, xen_string_string_map **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_string_map;

    *result = NULL;
    XEN_CALL_("host.get_software_version");
    return session->ok;
}


bool
xen_host_get_other_config(xen_session *session, xen_string_string_map **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_string_map;

    *result = NULL;
    XEN_CALL_("host.get_other_config");
    return session->ok;
}


bool
xen_host_get_capabilities(xen_session *session, struct xen_string_set **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    XEN_CALL_("host.get_capabilities");
    return session->ok;
}


bool
xen_host_get_supported_bootloaders(xen_session *session, struct xen_string_set **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    XEN_CALL_("host.get_supported_bootloaders");
    return session->ok;
}


bool
xen_host_get_resident_vms(xen_session *session, struct xen_vm_set **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    XEN_CALL_("host.get_resident_VMs");
    return session->ok;
}


bool
xen_host_get_logging(xen_session *session, xen_string_string_map **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_string_map;

    *result = NULL;
    XEN_CALL_("host.get_logging");
    return session->ok;
}


bool
xen_host_get_pifs(xen_session *session, struct xen_pif_set **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    XEN_CALL_("host.get_PIFs");
    return session->ok;
}


bool
xen_host_get_suspend_image_sr(xen_session *session, xen_sr *result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_suspend_image_sr");
    return session->ok;
}


bool
xen_host_get_crash_dump_sr(xen_session *session, xen_sr *result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_crash_dump_sr");
    return session->ok;
}


bool
xen_host_get_pbds(xen_session *session, struct xen_pbd_set **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    XEN_CALL_("host.get_PBDs");
    return session->ok;
}


bool
xen_host_get_host_cpus(xen_session *session, struct xen_host_cpu_set **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    XEN_CALL_("host.get_host_CPUs");
    return session->ok;
}


bool
xen_host_get_metrics(xen_session *session, xen_host_metrics *result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_metrics");
    return session->ok;
}


bool
xen_host_set_name_label(xen_session *session, xen_host host, char *label)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = label }
        };

    xen_call_(session, "host.set_name_label", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_set_name_description(xen_session *session, xen_host host, char *description)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = description }
        };

    xen_call_(session, "host.set_name_description", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_set_other_config(xen_session *session, xen_host host, xen_string_string_map *other_config)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string_string_map,
              .u.set_val = (arbitrary_set *)other_config }
        };

    xen_call_(session, "host.set_other_config", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_add_to_other_config(xen_session *session, xen_host host, char *key, char *value)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = key },
            { .type = &abstract_type_string,
              .u.string_val = value }
        };

    xen_call_(session, "host.add_to_other_config", param_values, 3, NULL, NULL);
    return session->ok;
}


bool
xen_host_remove_from_other_config(xen_session *session, xen_host host, char *key)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = key }
        };

    xen_call_(session, "host.remove_from_other_config", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_set_logging(xen_session *session, xen_host host, xen_string_string_map *logging)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string_string_map,
              .u.set_val = (arbitrary_set *)logging }
        };

    xen_call_(session, "host.set_logging", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_add_to_logging(xen_session *session, xen_host host, char *key, char *value)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = key },
            { .type = &abstract_type_string,
              .u.string_val = value }
        };

    xen_call_(session, "host.add_to_logging", param_values, 3, NULL, NULL);
    return session->ok;
}


bool
xen_host_remove_from_logging(xen_session *session, xen_host host, char *key)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = key }
        };

    xen_call_(session, "host.remove_from_logging", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_set_suspend_image_sr(xen_session *session, xen_host host, xen_sr suspend_image_sr)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = suspend_image_sr }
        };

    xen_call_(session, "host.set_suspend_image_sr", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_set_crash_dump_sr(xen_session *session, xen_host host, xen_sr crash_dump_sr)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host },
            { .type = &abstract_type_string,
              .u.string_val = crash_dump_sr }
        };

    xen_call_(session, "host.set_crash_dump_sr", param_values, 2, NULL, NULL);
    return session->ok;
}


bool
xen_host_disable(xen_session *session, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    xen_call_(session, "host.disable", param_values, 1, NULL, NULL);
    return session->ok;
}


bool
xen_host_enable(xen_session *session, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    xen_call_(session, "host.enable", param_values, 1, NULL, NULL);
    return session->ok;
}


bool
xen_host_shutdown(xen_session *session, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    xen_call_(session, "host.shutdown", param_values, 1, NULL, NULL);
    return session->ok;
}


bool
xen_host_reboot(xen_session *session, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    xen_call_(session, "host.reboot", param_values, 1, NULL, NULL);
    return session->ok;
}


bool
xen_host_dmesg(xen_session *session, char **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.dmesg");
    return session->ok;
}


bool
xen_host_get_all(xen_session *session, struct xen_host_set **result)
{

    abstract_type result_type = abstract_type_string_set;

    *result = NULL;
    xen_call_(session, "host.get_all", NULL, 0, &result_type, result);
    return session->ok;
}


bool
xen_host_get_uuid(xen_session *session, char **result, xen_host host)
{
    abstract_value param_values[] =
        {
            { .type = &abstract_type_string,
              .u.string_val = host }
        };

    abstract_type result_type = abstract_type_string;

    *result = NULL;
    XEN_CALL_("host.get_uuid");
    return session->ok;
}