xref: /illumos-gate/usr/src/cmd/bhyve/basl.c (revision 32640292)
159d65d31SAndy Fiddaman /*-
259d65d31SAndy Fiddaman  * SPDX-License-Identifier: BSD-2-Clause
359d65d31SAndy Fiddaman  *
459d65d31SAndy Fiddaman  * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG
559d65d31SAndy Fiddaman  */
659d65d31SAndy Fiddaman 
759d65d31SAndy Fiddaman #include <sys/param.h>
859d65d31SAndy Fiddaman #include <sys/endian.h>
959d65d31SAndy Fiddaman #include <sys/errno.h>
1059d65d31SAndy Fiddaman #include <sys/queue.h>
1159d65d31SAndy Fiddaman #include <sys/stat.h>
1259d65d31SAndy Fiddaman 
1359d65d31SAndy Fiddaman #include <machine/vmm.h>
1459d65d31SAndy Fiddaman 
1559d65d31SAndy Fiddaman #include <assert.h>
1659d65d31SAndy Fiddaman #include <err.h>
1759d65d31SAndy Fiddaman #include <libutil.h>
1859d65d31SAndy Fiddaman #include <stddef.h>
1959d65d31SAndy Fiddaman #include <stdio.h>
2059d65d31SAndy Fiddaman #include <vmmapi.h>
2159d65d31SAndy Fiddaman 
2259d65d31SAndy Fiddaman #ifndef	__FreeBSD__
2359d65d31SAndy Fiddaman #include "hexdump.h"
2459d65d31SAndy Fiddaman #endif
2559d65d31SAndy Fiddaman 
2659d65d31SAndy Fiddaman #include "basl.h"
27*32640292SAndy Fiddaman #include "config.h"
28*32640292SAndy Fiddaman #include "qemu_loader.h"
2959d65d31SAndy Fiddaman 
3059d65d31SAndy Fiddaman struct basl_table_checksum {
3159d65d31SAndy Fiddaman 	STAILQ_ENTRY(basl_table_checksum) chain;
3259d65d31SAndy Fiddaman 	uint32_t off;
3359d65d31SAndy Fiddaman 	uint32_t start;
3459d65d31SAndy Fiddaman 	uint32_t len;
3559d65d31SAndy Fiddaman };
3659d65d31SAndy Fiddaman 
3759d65d31SAndy Fiddaman struct basl_table_length {
3859d65d31SAndy Fiddaman 	STAILQ_ENTRY(basl_table_length) chain;
3959d65d31SAndy Fiddaman 	uint32_t off;
4059d65d31SAndy Fiddaman 	uint8_t size;
4159d65d31SAndy Fiddaman };
4259d65d31SAndy Fiddaman 
4359d65d31SAndy Fiddaman struct basl_table_pointer {
4459d65d31SAndy Fiddaman 	STAILQ_ENTRY(basl_table_pointer) chain;
4559d65d31SAndy Fiddaman 	uint8_t src_signature[ACPI_NAMESEG_SIZE];
4659d65d31SAndy Fiddaman 	uint32_t off;
4759d65d31SAndy Fiddaman 	uint8_t size;
4859d65d31SAndy Fiddaman };
4959d65d31SAndy Fiddaman 
5059d65d31SAndy Fiddaman struct basl_table {
5159d65d31SAndy Fiddaman 	STAILQ_ENTRY(basl_table) chain;
5259d65d31SAndy Fiddaman 	struct vmctx *ctx;
5359d65d31SAndy Fiddaman 	uint8_t fwcfg_name[QEMU_FWCFG_MAX_NAME];
5459d65d31SAndy Fiddaman 	void *data;
5559d65d31SAndy Fiddaman 	uint32_t len;
5659d65d31SAndy Fiddaman 	uint32_t off;
5759d65d31SAndy Fiddaman 	uint32_t alignment;
5859d65d31SAndy Fiddaman 	STAILQ_HEAD(basl_table_checksum_list, basl_table_checksum) checksums;
5959d65d31SAndy Fiddaman 	STAILQ_HEAD(basl_table_length_list, basl_table_length) lengths;
6059d65d31SAndy Fiddaman 	STAILQ_HEAD(basl_table_pointer_list, basl_table_pointer) pointers;
6159d65d31SAndy Fiddaman };
6259d65d31SAndy Fiddaman static STAILQ_HEAD(basl_table_list, basl_table) basl_tables = STAILQ_HEAD_INITIALIZER(
6359d65d31SAndy Fiddaman     basl_tables);
6459d65d31SAndy Fiddaman 
65*32640292SAndy Fiddaman static struct qemu_loader *basl_loader;
66*32640292SAndy Fiddaman static struct basl_table *rsdt;
67*32640292SAndy Fiddaman static struct basl_table *xsdt;
68*32640292SAndy Fiddaman static bool load_into_memory;
69*32640292SAndy Fiddaman 
7059d65d31SAndy Fiddaman static __inline uint64_t
basl_le_dec(void * pp,size_t len)7159d65d31SAndy Fiddaman basl_le_dec(void *pp, size_t len)
7259d65d31SAndy Fiddaman {
7359d65d31SAndy Fiddaman 	assert(len <= 8);
7459d65d31SAndy Fiddaman 
7559d65d31SAndy Fiddaman 	switch (len) {
7659d65d31SAndy Fiddaman 	case 1:
7759d65d31SAndy Fiddaman 		return ((uint8_t *)pp)[0];
7859d65d31SAndy Fiddaman 	case 2:
7959d65d31SAndy Fiddaman 		return le16dec(pp);
8059d65d31SAndy Fiddaman 	case 4:
8159d65d31SAndy Fiddaman 		return le32dec(pp);
8259d65d31SAndy Fiddaman 	case 8:
8359d65d31SAndy Fiddaman 		return le64dec(pp);
8459d65d31SAndy Fiddaman 	}
8559d65d31SAndy Fiddaman 
8659d65d31SAndy Fiddaman 	return 0;
8759d65d31SAndy Fiddaman }
8859d65d31SAndy Fiddaman 
8959d65d31SAndy Fiddaman static __inline void
basl_le_enc(void * pp,uint64_t val,size_t len)9059d65d31SAndy Fiddaman basl_le_enc(void *pp, uint64_t val, size_t len)
9159d65d31SAndy Fiddaman {
9259d65d31SAndy Fiddaman 	char buf[8];
9359d65d31SAndy Fiddaman 
9459d65d31SAndy Fiddaman 	assert(len <= 8);
9559d65d31SAndy Fiddaman 
9659d65d31SAndy Fiddaman 	le64enc(buf, val);
9759d65d31SAndy Fiddaman 	memcpy(pp, buf, len);
9859d65d31SAndy Fiddaman }
9959d65d31SAndy Fiddaman 
10059d65d31SAndy Fiddaman static int
basl_dump_table(const struct basl_table * const table,const bool mem)10159d65d31SAndy Fiddaman basl_dump_table(const struct basl_table *const table, const bool mem)
10259d65d31SAndy Fiddaman {
10359d65d31SAndy Fiddaman 	const ACPI_TABLE_HEADER *const header = table->data;
10459d65d31SAndy Fiddaman 	const uint8_t *data;
10559d65d31SAndy Fiddaman 
10659d65d31SAndy Fiddaman 	if (!mem) {
10759d65d31SAndy Fiddaman 		data = table->data;
10859d65d31SAndy Fiddaman 	} else {
10959d65d31SAndy Fiddaman 		data = vm_map_gpa(table->ctx, BHYVE_ACPI_BASE + table->off,
11059d65d31SAndy Fiddaman 		    table->len);
11159d65d31SAndy Fiddaman 		if (data == NULL) {
11259d65d31SAndy Fiddaman 			return (ENOMEM);
11359d65d31SAndy Fiddaman 		}
11459d65d31SAndy Fiddaman 	}
11559d65d31SAndy Fiddaman 
11659d65d31SAndy Fiddaman 	printf("%.4s @ %8x (%s)\n", header->Signature,
11759d65d31SAndy Fiddaman 	    BHYVE_ACPI_BASE + table->off, mem ? "Memory" : "FwCfg");
11859d65d31SAndy Fiddaman 	hexdump(data, table->len, NULL, 0);
11959d65d31SAndy Fiddaman 
12059d65d31SAndy Fiddaman 	return (0);
12159d65d31SAndy Fiddaman }
12259d65d31SAndy Fiddaman 
12359d65d31SAndy Fiddaman static int __unused
basl_dump(const bool mem)12459d65d31SAndy Fiddaman basl_dump(const bool mem)
12559d65d31SAndy Fiddaman {
12659d65d31SAndy Fiddaman 	struct basl_table *table;
12759d65d31SAndy Fiddaman 
12859d65d31SAndy Fiddaman 	STAILQ_FOREACH(table, &basl_tables, chain) {
12959d65d31SAndy Fiddaman 		BASL_EXEC(basl_dump_table(table, mem));
13059d65d31SAndy Fiddaman 	}
13159d65d31SAndy Fiddaman 
13259d65d31SAndy Fiddaman 	return (0);
13359d65d31SAndy Fiddaman }
13459d65d31SAndy Fiddaman 
13559d65d31SAndy Fiddaman void
basl_fill_gas(ACPI_GENERIC_ADDRESS * const gas,const uint8_t space_id,const uint8_t bit_width,const uint8_t bit_offset,const uint8_t access_width,const uint64_t address)13659d65d31SAndy Fiddaman basl_fill_gas(ACPI_GENERIC_ADDRESS *const gas, const uint8_t space_id,
13759d65d31SAndy Fiddaman     const uint8_t bit_width, const uint8_t bit_offset,
13859d65d31SAndy Fiddaman     const uint8_t access_width, const uint64_t address)
13959d65d31SAndy Fiddaman {
14059d65d31SAndy Fiddaman 	assert(gas != NULL);
14159d65d31SAndy Fiddaman 
14259d65d31SAndy Fiddaman 	gas->SpaceId = space_id;
14359d65d31SAndy Fiddaman 	gas->BitWidth = bit_width;
14459d65d31SAndy Fiddaman 	gas->BitOffset = bit_offset;
14559d65d31SAndy Fiddaman 	gas->AccessWidth = access_width;
14659d65d31SAndy Fiddaman 	gas->Address = htole64(address);
14759d65d31SAndy Fiddaman }
14859d65d31SAndy Fiddaman 
14959d65d31SAndy Fiddaman static int
basl_finish_install_guest_tables(struct basl_table * const table,uint32_t * const off)15059d65d31SAndy Fiddaman basl_finish_install_guest_tables(struct basl_table *const table, uint32_t *const off)
15159d65d31SAndy Fiddaman {
15259d65d31SAndy Fiddaman 	void *gva;
15359d65d31SAndy Fiddaman 
15459d65d31SAndy Fiddaman 	table->off = roundup2(*off, table->alignment);
15559d65d31SAndy Fiddaman 	*off = table->off + table->len;
15659d65d31SAndy Fiddaman 	if (*off <= table->off) {
15759d65d31SAndy Fiddaman 		warnx("%s: invalid table length 0x%8x @ offset 0x%8x", __func__,
15859d65d31SAndy Fiddaman 		    table->len, table->off);
15959d65d31SAndy Fiddaman 		return (EFAULT);
16059d65d31SAndy Fiddaman 	}
16159d65d31SAndy Fiddaman 
162*32640292SAndy Fiddaman 	/* Cause guest BIOS to copy the ACPI table into guest memory. */
163*32640292SAndy Fiddaman #ifdef	__FreeBSD__
164*32640292SAndy Fiddaman 	BASL_EXEC(
165*32640292SAndy Fiddaman 	    qemu_fwcfg_add_file(table->fwcfg_name, table->len, table->data));
166*32640292SAndy Fiddaman #else
167*32640292SAndy Fiddaman 	BASL_EXEC(
168*32640292SAndy Fiddaman 	    qemu_fwcfg_add_file((const char *)table->fwcfg_name,
169*32640292SAndy Fiddaman 	    table->len, table->data));
170*32640292SAndy Fiddaman #endif
171*32640292SAndy Fiddaman 	BASL_EXEC(qemu_loader_alloc(basl_loader, table->fwcfg_name,
172*32640292SAndy Fiddaman 	    table->alignment, QEMU_LOADER_ALLOC_HIGH));
173*32640292SAndy Fiddaman 
174*32640292SAndy Fiddaman 	if (!load_into_memory) {
175*32640292SAndy Fiddaman 		return (0);
176*32640292SAndy Fiddaman 	}
177*32640292SAndy Fiddaman 
17859d65d31SAndy Fiddaman 	/*
17959d65d31SAndy Fiddaman 	 * Install ACPI tables directly in guest memory for use by guests which
18059d65d31SAndy Fiddaman 	 * do not boot via EFI. EFI ROMs provide a pointer to the firmware
18159d65d31SAndy Fiddaman 	 * generated ACPI tables instead, but it doesn't hurt to install the
18259d65d31SAndy Fiddaman 	 * tables always.
18359d65d31SAndy Fiddaman 	 */
18459d65d31SAndy Fiddaman 	gva = vm_map_gpa(table->ctx, BHYVE_ACPI_BASE + table->off, table->len);
18559d65d31SAndy Fiddaman 	if (gva == NULL) {
18659d65d31SAndy Fiddaman 		warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]", __func__,
18759d65d31SAndy Fiddaman 		    (uint64_t)BHYVE_ACPI_BASE + table->off,
18859d65d31SAndy Fiddaman 		    (uint64_t)BHYVE_ACPI_BASE + table->off + table->len);
18959d65d31SAndy Fiddaman 		return (ENOMEM);
19059d65d31SAndy Fiddaman 	}
19159d65d31SAndy Fiddaman 	memcpy(gva, table->data, table->len);
19259d65d31SAndy Fiddaman 
19359d65d31SAndy Fiddaman 	return (0);
19459d65d31SAndy Fiddaman }
19559d65d31SAndy Fiddaman 
19659d65d31SAndy Fiddaman static int
basl_finish_patch_checksums(struct basl_table * const table)19759d65d31SAndy Fiddaman basl_finish_patch_checksums(struct basl_table *const table)
19859d65d31SAndy Fiddaman {
19959d65d31SAndy Fiddaman 	struct basl_table_checksum *checksum;
20059d65d31SAndy Fiddaman 
20159d65d31SAndy Fiddaman 	STAILQ_FOREACH(checksum, &table->checksums, chain) {
20259d65d31SAndy Fiddaman 		uint8_t *gva, *checksum_gva;
20359d65d31SAndy Fiddaman 		uint64_t gpa;
20459d65d31SAndy Fiddaman 		uint32_t len;
20559d65d31SAndy Fiddaman 		uint8_t sum;
20659d65d31SAndy Fiddaman 
20759d65d31SAndy Fiddaman 		len = checksum->len;
20859d65d31SAndy Fiddaman 		if (len == BASL_TABLE_CHECKSUM_LEN_FULL_TABLE) {
20959d65d31SAndy Fiddaman 			len = table->len;
21059d65d31SAndy Fiddaman 		}
21159d65d31SAndy Fiddaman 
21259d65d31SAndy Fiddaman 		assert(checksum->off < table->len);
21359d65d31SAndy Fiddaman 		assert(checksum->start < table->len);
21459d65d31SAndy Fiddaman 		assert(checksum->start + len <= table->len);
21559d65d31SAndy Fiddaman 
216*32640292SAndy Fiddaman 		/* Cause guest BIOS to patch the checksum. */
217*32640292SAndy Fiddaman 		BASL_EXEC(qemu_loader_add_checksum(basl_loader,
218*32640292SAndy Fiddaman 		    table->fwcfg_name, checksum->off, checksum->start, len));
219*32640292SAndy Fiddaman 
220*32640292SAndy Fiddaman 		if (!load_into_memory) {
221*32640292SAndy Fiddaman 			continue;
222*32640292SAndy Fiddaman 		}
223*32640292SAndy Fiddaman 
22459d65d31SAndy Fiddaman 		/*
22559d65d31SAndy Fiddaman 		 * Install ACPI tables directly in guest memory for use by
22659d65d31SAndy Fiddaman 		 * guests which do not boot via EFI. EFI ROMs provide a pointer
22759d65d31SAndy Fiddaman 		 * to the firmware generated ACPI tables instead, but it doesn't
22859d65d31SAndy Fiddaman 		 * hurt to install the tables always.
22959d65d31SAndy Fiddaman 		 */
23059d65d31SAndy Fiddaman 		gpa = BHYVE_ACPI_BASE + table->off + checksum->start;
23159d65d31SAndy Fiddaman 		if ((gpa < BHYVE_ACPI_BASE) ||
23259d65d31SAndy Fiddaman 		    (gpa < BHYVE_ACPI_BASE + table->off)) {
23359d65d31SAndy Fiddaman 			warnx("%s: invalid gpa (off 0x%8x start 0x%8x)",
23459d65d31SAndy Fiddaman 			    __func__, table->off, checksum->start);
23559d65d31SAndy Fiddaman 			return (EFAULT);
23659d65d31SAndy Fiddaman 		}
23759d65d31SAndy Fiddaman 
23859d65d31SAndy Fiddaman 		gva = vm_map_gpa(table->ctx, gpa, len);
23959d65d31SAndy Fiddaman 		if (gva == NULL) {
24059d65d31SAndy Fiddaman 			warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
24159d65d31SAndy Fiddaman 			    __func__, gpa, gpa + len);
24259d65d31SAndy Fiddaman 			return (ENOMEM);
24359d65d31SAndy Fiddaman 		}
24459d65d31SAndy Fiddaman 
24559d65d31SAndy Fiddaman 		checksum_gva = gva + checksum->off;
24659d65d31SAndy Fiddaman 		if (checksum_gva < gva) {
24759d65d31SAndy Fiddaman 			warnx("%s: invalid checksum offset 0x%8x", __func__,
24859d65d31SAndy Fiddaman 			    checksum->off);
24959d65d31SAndy Fiddaman 			return (EFAULT);
25059d65d31SAndy Fiddaman 		}
25159d65d31SAndy Fiddaman 
25259d65d31SAndy Fiddaman 		sum = 0;
25359d65d31SAndy Fiddaman 		for (uint32_t i = 0; i < len; ++i) {
25459d65d31SAndy Fiddaman 			sum += *(gva + i);
25559d65d31SAndy Fiddaman 		}
25659d65d31SAndy Fiddaman 		*checksum_gva = -sum;
25759d65d31SAndy Fiddaman 	}
25859d65d31SAndy Fiddaman 
25959d65d31SAndy Fiddaman 	return (0);
26059d65d31SAndy Fiddaman }
26159d65d31SAndy Fiddaman 
26259d65d31SAndy Fiddaman static struct basl_table *
basl_get_table_by_signature(const uint8_t signature[ACPI_NAMESEG_SIZE])26359d65d31SAndy Fiddaman basl_get_table_by_signature(const uint8_t signature[ACPI_NAMESEG_SIZE])
26459d65d31SAndy Fiddaman {
26559d65d31SAndy Fiddaman 	struct basl_table *table;
26659d65d31SAndy Fiddaman 
26759d65d31SAndy Fiddaman 	STAILQ_FOREACH(table, &basl_tables, chain) {
26859d65d31SAndy Fiddaman 		const ACPI_TABLE_HEADER *const header =
26959d65d31SAndy Fiddaman 		    (const ACPI_TABLE_HEADER *)table->data;
27059d65d31SAndy Fiddaman 
27159d65d31SAndy Fiddaman #ifdef	__FreeBSD__
27259d65d31SAndy Fiddaman 		if (strncmp(header->Signature, signature,
27359d65d31SAndy Fiddaman 			sizeof(header->Signature)) == 0) {
27459d65d31SAndy Fiddaman 			return (table);
27559d65d31SAndy Fiddaman #else
27659d65d31SAndy Fiddaman 		if (strncmp(header->Signature, (char *)signature,
27759d65d31SAndy Fiddaman 			sizeof(header->Signature)) == 0) {
27859d65d31SAndy Fiddaman 			return (table);
27959d65d31SAndy Fiddaman #endif
28059d65d31SAndy Fiddaman 		}
28159d65d31SAndy Fiddaman 	}
28259d65d31SAndy Fiddaman 
28359d65d31SAndy Fiddaman 	warnx("%s: %.4s not found", __func__, signature);
28459d65d31SAndy Fiddaman 	return (NULL);
28559d65d31SAndy Fiddaman }
28659d65d31SAndy Fiddaman 
28759d65d31SAndy Fiddaman static int
28859d65d31SAndy Fiddaman basl_finish_patch_pointers(struct basl_table *const table)
28959d65d31SAndy Fiddaman {
29059d65d31SAndy Fiddaman 	struct basl_table_pointer *pointer;
29159d65d31SAndy Fiddaman 
29259d65d31SAndy Fiddaman 	STAILQ_FOREACH(pointer, &table->pointers, chain) {
29359d65d31SAndy Fiddaman 		const struct basl_table *src_table;
29459d65d31SAndy Fiddaman 		uint8_t *gva;
29559d65d31SAndy Fiddaman 		uint64_t gpa, val;
29659d65d31SAndy Fiddaman 
29759d65d31SAndy Fiddaman 		assert(pointer->off < table->len);
29859d65d31SAndy Fiddaman 		assert(pointer->off + pointer->size <= table->len);
29959d65d31SAndy Fiddaman 
30059d65d31SAndy Fiddaman 		src_table = basl_get_table_by_signature(pointer->src_signature);
30159d65d31SAndy Fiddaman 		if (src_table == NULL) {
30259d65d31SAndy Fiddaman 			warnx("%s: could not find ACPI table %.4s", __func__,
30359d65d31SAndy Fiddaman 			    pointer->src_signature);
30459d65d31SAndy Fiddaman 			return (EFAULT);
30559d65d31SAndy Fiddaman 		}
30659d65d31SAndy Fiddaman 
307*32640292SAndy Fiddaman 		/* Cause guest BIOS to patch the pointer. */
308*32640292SAndy Fiddaman 		BASL_EXEC(
309*32640292SAndy Fiddaman 		    qemu_loader_add_pointer(basl_loader, table->fwcfg_name,
310*32640292SAndy Fiddaman 			src_table->fwcfg_name, pointer->off, pointer->size));
311*32640292SAndy Fiddaman 
312*32640292SAndy Fiddaman 		if (!load_into_memory) {
313*32640292SAndy Fiddaman 			continue;
314*32640292SAndy Fiddaman 		}
315*32640292SAndy Fiddaman 
31659d65d31SAndy Fiddaman 		/*
31759d65d31SAndy Fiddaman 		 * Install ACPI tables directly in guest memory for use by
31859d65d31SAndy Fiddaman 		 * guests which do not boot via EFI. EFI ROMs provide a pointer
31959d65d31SAndy Fiddaman 		 * to the firmware generated ACPI tables instead, but it doesn't
32059d65d31SAndy Fiddaman 		 * hurt to install the tables always.
32159d65d31SAndy Fiddaman 		 */
32259d65d31SAndy Fiddaman 		gpa = BHYVE_ACPI_BASE + table->off;
32359d65d31SAndy Fiddaman 		if (gpa < BHYVE_ACPI_BASE) {
32459d65d31SAndy Fiddaman 			warnx("%s: table offset of 0x%8x is too large",
32559d65d31SAndy Fiddaman 			    __func__, table->off);
32659d65d31SAndy Fiddaman 			return (EFAULT);
32759d65d31SAndy Fiddaman 		}
32859d65d31SAndy Fiddaman 
32959d65d31SAndy Fiddaman 		gva = vm_map_gpa(table->ctx, gpa, table->len);
33059d65d31SAndy Fiddaman 		if (gva == NULL) {
33159d65d31SAndy Fiddaman 			warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
33259d65d31SAndy Fiddaman 			    __func__, gpa, gpa + table->len);
33359d65d31SAndy Fiddaman 			return (ENOMEM);
33459d65d31SAndy Fiddaman 		}
33559d65d31SAndy Fiddaman 
33659d65d31SAndy Fiddaman 		val = basl_le_dec(gva + pointer->off, pointer->size);
33759d65d31SAndy Fiddaman 		val += BHYVE_ACPI_BASE + src_table->off;
33859d65d31SAndy Fiddaman 		basl_le_enc(gva + pointer->off, val, pointer->size);
33959d65d31SAndy Fiddaman 	}
34059d65d31SAndy Fiddaman 
34159d65d31SAndy Fiddaman 	return (0);
34259d65d31SAndy Fiddaman }
34359d65d31SAndy Fiddaman 
34459d65d31SAndy Fiddaman static int
34559d65d31SAndy Fiddaman basl_finish_set_length(struct basl_table *const table)
34659d65d31SAndy Fiddaman {
34759d65d31SAndy Fiddaman 	struct basl_table_length *length;
34859d65d31SAndy Fiddaman 
34959d65d31SAndy Fiddaman 	STAILQ_FOREACH(length, &table->lengths, chain) {
35059d65d31SAndy Fiddaman 		assert(length->off < table->len);
35159d65d31SAndy Fiddaman 		assert(length->off + length->size <= table->len);
35259d65d31SAndy Fiddaman 
35359d65d31SAndy Fiddaman 		basl_le_enc((uint8_t *)table->data + length->off, table->len,
35459d65d31SAndy Fiddaman 		    length->size);
35559d65d31SAndy Fiddaman 	}
35659d65d31SAndy Fiddaman 
35759d65d31SAndy Fiddaman 	return (0);
35859d65d31SAndy Fiddaman }
35959d65d31SAndy Fiddaman 
36059d65d31SAndy Fiddaman int
36159d65d31SAndy Fiddaman basl_finish(void)
36259d65d31SAndy Fiddaman {
36359d65d31SAndy Fiddaman 	struct basl_table *table;
36459d65d31SAndy Fiddaman 	uint32_t off = 0;
36559d65d31SAndy Fiddaman 
36659d65d31SAndy Fiddaman 	if (STAILQ_EMPTY(&basl_tables)) {
36759d65d31SAndy Fiddaman 		warnx("%s: no ACPI tables found", __func__);
36859d65d31SAndy Fiddaman 		return (EINVAL);
36959d65d31SAndy Fiddaman 	}
37059d65d31SAndy Fiddaman 
371*32640292SAndy Fiddaman 	/*
372*32640292SAndy Fiddaman 	 * If we install ACPI tables by FwCfg and by memory, Windows will use
373*32640292SAndy Fiddaman 	 * the tables from memory. This can cause issues when using advanced
374*32640292SAndy Fiddaman 	 * features like a TPM log because we aren't able to patch the memory
375*32640292SAndy Fiddaman 	 * tables accordingly.
376*32640292SAndy Fiddaman 	 */
377*32640292SAndy Fiddaman 	load_into_memory = get_config_bool_default("acpi_tables_in_memory",
378*32640292SAndy Fiddaman 	    true);
379*32640292SAndy Fiddaman 
38059d65d31SAndy Fiddaman 	/*
38159d65d31SAndy Fiddaman 	 * We have to install all tables before we can patch them. Therefore,
38259d65d31SAndy Fiddaman 	 * use two loops. The first one installs all tables and the second one
38359d65d31SAndy Fiddaman 	 * patches them.
38459d65d31SAndy Fiddaman 	 */
38559d65d31SAndy Fiddaman 	STAILQ_FOREACH(table, &basl_tables, chain) {
38659d65d31SAndy Fiddaman 		BASL_EXEC(basl_finish_set_length(table));
38759d65d31SAndy Fiddaman 		BASL_EXEC(basl_finish_install_guest_tables(table, &off));
38859d65d31SAndy Fiddaman 	}
38959d65d31SAndy Fiddaman 	STAILQ_FOREACH(table, &basl_tables, chain) {
39059d65d31SAndy Fiddaman 		BASL_EXEC(basl_finish_patch_pointers(table));
39159d65d31SAndy Fiddaman 
39259d65d31SAndy Fiddaman 		/*
39359d65d31SAndy Fiddaman 		 * Calculate the checksum as last step!
39459d65d31SAndy Fiddaman 		 */
39559d65d31SAndy Fiddaman 		BASL_EXEC(basl_finish_patch_checksums(table));
39659d65d31SAndy Fiddaman 	}
397*32640292SAndy Fiddaman 	BASL_EXEC(qemu_loader_finish(basl_loader));
398*32640292SAndy Fiddaman 
399*32640292SAndy Fiddaman 	return (0);
400*32640292SAndy Fiddaman }
401*32640292SAndy Fiddaman 
402*32640292SAndy Fiddaman static int
403*32640292SAndy Fiddaman basl_init_rsdt(struct vmctx *const ctx)
404*32640292SAndy Fiddaman {
405*32640292SAndy Fiddaman 	BASL_EXEC(
406*32640292SAndy Fiddaman 	    basl_table_create(&rsdt, ctx, ACPI_SIG_RSDT, BASL_TABLE_ALIGNMENT));
407*32640292SAndy Fiddaman 
408*32640292SAndy Fiddaman 	/* Header */
409*32640292SAndy Fiddaman 	BASL_EXEC(basl_table_append_header(rsdt, ACPI_SIG_RSDT, 1, 1));
410*32640292SAndy Fiddaman 	/* Pointers (added by basl_table_register_to_rsdt) */
411*32640292SAndy Fiddaman 
412*32640292SAndy Fiddaman 	return (0);
413*32640292SAndy Fiddaman }
414*32640292SAndy Fiddaman 
415*32640292SAndy Fiddaman static int
416*32640292SAndy Fiddaman basl_init_xsdt(struct vmctx *const ctx)
417*32640292SAndy Fiddaman {
418*32640292SAndy Fiddaman 	BASL_EXEC(
419*32640292SAndy Fiddaman 	    basl_table_create(&xsdt, ctx, ACPI_SIG_XSDT, BASL_TABLE_ALIGNMENT));
420*32640292SAndy Fiddaman 
421*32640292SAndy Fiddaman 	/* Header */
422*32640292SAndy Fiddaman 	BASL_EXEC(basl_table_append_header(xsdt, ACPI_SIG_XSDT, 1, 1));
423*32640292SAndy Fiddaman 	/* Pointers (added by basl_table_register_to_rsdt) */
42459d65d31SAndy Fiddaman 
42559d65d31SAndy Fiddaman 	return (0);
42659d65d31SAndy Fiddaman }
42759d65d31SAndy Fiddaman 
42859d65d31SAndy Fiddaman int
429*32640292SAndy Fiddaman basl_init(struct vmctx *const ctx)
43059d65d31SAndy Fiddaman {
431*32640292SAndy Fiddaman 	BASL_EXEC(basl_init_rsdt(ctx));
432*32640292SAndy Fiddaman 	BASL_EXEC(basl_init_xsdt(ctx));
433*32640292SAndy Fiddaman #ifdef	__FreeBSD__
434*32640292SAndy Fiddaman 	BASL_EXEC(
435*32640292SAndy Fiddaman 	    qemu_loader_create(&basl_loader, QEMU_FWCFG_FILE_TABLE_LOADER));
436*32640292SAndy Fiddaman #else
437*32640292SAndy Fiddaman 	BASL_EXEC(
438*32640292SAndy Fiddaman 	    qemu_loader_create(&basl_loader,
439*32640292SAndy Fiddaman 	    (uint8_t *)QEMU_FWCFG_FILE_TABLE_LOADER));
440*32640292SAndy Fiddaman #endif
441*32640292SAndy Fiddaman 
44259d65d31SAndy Fiddaman 	return (0);
44359d65d31SAndy Fiddaman }
44459d65d31SAndy Fiddaman 
44559d65d31SAndy Fiddaman int
44659d65d31SAndy Fiddaman basl_table_add_checksum(struct basl_table *const table, const uint32_t off,
44759d65d31SAndy Fiddaman     const uint32_t start, const uint32_t len)
44859d65d31SAndy Fiddaman {
44959d65d31SAndy Fiddaman 	struct basl_table_checksum *checksum;
45059d65d31SAndy Fiddaman 
45159d65d31SAndy Fiddaman 	assert(table != NULL);
45259d65d31SAndy Fiddaman 
45359d65d31SAndy Fiddaman 	checksum = calloc(1, sizeof(struct basl_table_checksum));
45459d65d31SAndy Fiddaman 	if (checksum == NULL) {
45559d65d31SAndy Fiddaman 		warnx("%s: failed to allocate checksum", __func__);
45659d65d31SAndy Fiddaman 		return (ENOMEM);
45759d65d31SAndy Fiddaman 	}
45859d65d31SAndy Fiddaman 
45959d65d31SAndy Fiddaman 	checksum->off = off;
46059d65d31SAndy Fiddaman 	checksum->start = start;
46159d65d31SAndy Fiddaman 	checksum->len = len;
46259d65d31SAndy Fiddaman 
46359d65d31SAndy Fiddaman 	STAILQ_INSERT_TAIL(&table->checksums, checksum, chain);
46459d65d31SAndy Fiddaman 
46559d65d31SAndy Fiddaman 	return (0);
46659d65d31SAndy Fiddaman }
46759d65d31SAndy Fiddaman 
46859d65d31SAndy Fiddaman int
46959d65d31SAndy Fiddaman basl_table_add_length(struct basl_table *const table, const uint32_t off,
47059d65d31SAndy Fiddaman     const uint8_t size)
47159d65d31SAndy Fiddaman {
47259d65d31SAndy Fiddaman 	struct basl_table_length *length;
47359d65d31SAndy Fiddaman 
47459d65d31SAndy Fiddaman 	assert(table != NULL);
47559d65d31SAndy Fiddaman 	assert(size == 4 || size == 8);
47659d65d31SAndy Fiddaman 
47759d65d31SAndy Fiddaman 	length = calloc(1, sizeof(struct basl_table_length));
47859d65d31SAndy Fiddaman 	if (length == NULL) {
47959d65d31SAndy Fiddaman 		warnx("%s: failed to allocate length", __func__);
48059d65d31SAndy Fiddaman 		return (ENOMEM);
48159d65d31SAndy Fiddaman 	}
48259d65d31SAndy Fiddaman 
48359d65d31SAndy Fiddaman 	length->off = off;
48459d65d31SAndy Fiddaman 	length->size = size;
48559d65d31SAndy Fiddaman 
48659d65d31SAndy Fiddaman 	STAILQ_INSERT_TAIL(&table->lengths, length, chain);
48759d65d31SAndy Fiddaman 
48859d65d31SAndy Fiddaman 	return (0);
48959d65d31SAndy Fiddaman }
49059d65d31SAndy Fiddaman 
49159d65d31SAndy Fiddaman int
49259d65d31SAndy Fiddaman basl_table_add_pointer(struct basl_table *const table,
49359d65d31SAndy Fiddaman     const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint32_t off,
49459d65d31SAndy Fiddaman     const uint8_t size)
49559d65d31SAndy Fiddaman {
49659d65d31SAndy Fiddaman 	struct basl_table_pointer *pointer;
49759d65d31SAndy Fiddaman 
49859d65d31SAndy Fiddaman 	assert(table != NULL);
49959d65d31SAndy Fiddaman 	assert(size == 4 || size == 8);
50059d65d31SAndy Fiddaman 
50159d65d31SAndy Fiddaman 	pointer = calloc(1, sizeof(struct basl_table_pointer));
50259d65d31SAndy Fiddaman 	if (pointer == NULL) {
50359d65d31SAndy Fiddaman 		warnx("%s: failed to allocate pointer", __func__);
50459d65d31SAndy Fiddaman 		return (ENOMEM);
50559d65d31SAndy Fiddaman 	}
50659d65d31SAndy Fiddaman 
50759d65d31SAndy Fiddaman 	memcpy(pointer->src_signature, src_signature,
50859d65d31SAndy Fiddaman 	    sizeof(pointer->src_signature));
50959d65d31SAndy Fiddaman 	pointer->off = off;
51059d65d31SAndy Fiddaman 	pointer->size = size;
51159d65d31SAndy Fiddaman 
51259d65d31SAndy Fiddaman 	STAILQ_INSERT_TAIL(&table->pointers, pointer, chain);
51359d65d31SAndy Fiddaman 
51459d65d31SAndy Fiddaman 	return (0);
51559d65d31SAndy Fiddaman }
51659d65d31SAndy Fiddaman 
51759d65d31SAndy Fiddaman int
51859d65d31SAndy Fiddaman basl_table_append_bytes(struct basl_table *const table, const void *const bytes,
51959d65d31SAndy Fiddaman     const uint32_t len)
52059d65d31SAndy Fiddaman {
52159d65d31SAndy Fiddaman 	void *end;
52259d65d31SAndy Fiddaman 
52359d65d31SAndy Fiddaman 	assert(table != NULL);
52459d65d31SAndy Fiddaman 	assert(bytes != NULL);
52559d65d31SAndy Fiddaman 
52659d65d31SAndy Fiddaman 	if (table->len + len <= table->len) {
52759d65d31SAndy Fiddaman 		warnx("%s: table too large (table->len 0x%8x len 0x%8x)",
52859d65d31SAndy Fiddaman 		    __func__, table->len, len);
52959d65d31SAndy Fiddaman 		return (EFAULT);
53059d65d31SAndy Fiddaman 	}
53159d65d31SAndy Fiddaman 
53259d65d31SAndy Fiddaman 	table->data = reallocf(table->data, table->len + len);
53359d65d31SAndy Fiddaman 	if (table->data == NULL) {
53459d65d31SAndy Fiddaman 		warnx("%s: failed to realloc table to length 0x%8x", __func__,
53559d65d31SAndy Fiddaman 		    table->len + len);
53659d65d31SAndy Fiddaman 		table->len = 0;
53759d65d31SAndy Fiddaman 		return (ENOMEM);
53859d65d31SAndy Fiddaman 	}
53959d65d31SAndy Fiddaman 
54059d65d31SAndy Fiddaman 	end = (uint8_t *)table->data + table->len;
54159d65d31SAndy Fiddaman 	table->len += len;
54259d65d31SAndy Fiddaman 
54359d65d31SAndy Fiddaman 	memcpy(end, bytes, len);
54459d65d31SAndy Fiddaman 
54559d65d31SAndy Fiddaman 	return (0);
54659d65d31SAndy Fiddaman }
54759d65d31SAndy Fiddaman 
54859d65d31SAndy Fiddaman int
54959d65d31SAndy Fiddaman basl_table_append_checksum(struct basl_table *const table, const uint32_t start,
55059d65d31SAndy Fiddaman     const uint32_t len)
55159d65d31SAndy Fiddaman {
55259d65d31SAndy Fiddaman 	assert(table != NULL);
55359d65d31SAndy Fiddaman 
55459d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_add_checksum(table, table->len, start, len));
55559d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_append_int(table, 0, 1));
55659d65d31SAndy Fiddaman 
55759d65d31SAndy Fiddaman 	return (0);
55859d65d31SAndy Fiddaman }
55959d65d31SAndy Fiddaman 
56059d65d31SAndy Fiddaman int
56159d65d31SAndy Fiddaman basl_table_append_content(struct basl_table *table, void *data, uint32_t len)
56259d65d31SAndy Fiddaman {
56359d65d31SAndy Fiddaman 	assert(data != NULL);
56459d65d31SAndy Fiddaman 	assert(len >= sizeof(ACPI_TABLE_HEADER));
56559d65d31SAndy Fiddaman 
56659d65d31SAndy Fiddaman 	return (basl_table_append_bytes(table,
56759d65d31SAndy Fiddaman 	    (void *)((uintptr_t)(data) + sizeof(ACPI_TABLE_HEADER)),
56859d65d31SAndy Fiddaman 	    len - sizeof(ACPI_TABLE_HEADER)));
56959d65d31SAndy Fiddaman }
57059d65d31SAndy Fiddaman 
571*32640292SAndy Fiddaman int
572*32640292SAndy Fiddaman basl_table_append_fwcfg(struct basl_table *const table,
573*32640292SAndy Fiddaman     const uint8_t *fwcfg_name, const uint32_t alignment, const uint8_t size)
574*32640292SAndy Fiddaman {
575*32640292SAndy Fiddaman 	assert(table != NULL);
576*32640292SAndy Fiddaman 	assert(fwcfg_name != NULL);
577*32640292SAndy Fiddaman 	assert(size <= sizeof(uint64_t));
578*32640292SAndy Fiddaman 
579*32640292SAndy Fiddaman 	BASL_EXEC(qemu_loader_alloc(basl_loader, fwcfg_name, alignment,
580*32640292SAndy Fiddaman 	    QEMU_LOADER_ALLOC_HIGH));
581*32640292SAndy Fiddaman 	BASL_EXEC(qemu_loader_add_pointer(basl_loader, table->fwcfg_name,
582*32640292SAndy Fiddaman 	    fwcfg_name, table->len, size));
583*32640292SAndy Fiddaman 	BASL_EXEC(basl_table_append_int(table, 0, size));
584*32640292SAndy Fiddaman 
585*32640292SAndy Fiddaman 	return (0);
586*32640292SAndy Fiddaman }
587*32640292SAndy Fiddaman 
58859d65d31SAndy Fiddaman int
58959d65d31SAndy Fiddaman basl_table_append_gas(struct basl_table *const table, const uint8_t space_id,
59059d65d31SAndy Fiddaman     const uint8_t bit_width, const uint8_t bit_offset,
59159d65d31SAndy Fiddaman     const uint8_t access_width, const uint64_t address)
59259d65d31SAndy Fiddaman {
59359d65d31SAndy Fiddaman 	ACPI_GENERIC_ADDRESS gas_le = {
59459d65d31SAndy Fiddaman 		.SpaceId = space_id,
59559d65d31SAndy Fiddaman 		.BitWidth = bit_width,
59659d65d31SAndy Fiddaman 		.BitOffset = bit_offset,
59759d65d31SAndy Fiddaman 		.AccessWidth = access_width,
59859d65d31SAndy Fiddaman 		.Address = htole64(address),
59959d65d31SAndy Fiddaman 	};
60059d65d31SAndy Fiddaman 
60159d65d31SAndy Fiddaman 	return (basl_table_append_bytes(table, &gas_le, sizeof(gas_le)));
60259d65d31SAndy Fiddaman }
60359d65d31SAndy Fiddaman 
60459d65d31SAndy Fiddaman int
60559d65d31SAndy Fiddaman basl_table_append_header(struct basl_table *const table,
60659d65d31SAndy Fiddaman     const uint8_t signature[ACPI_NAMESEG_SIZE], const uint8_t revision,
60759d65d31SAndy Fiddaman     const uint32_t oem_revision)
60859d65d31SAndy Fiddaman {
60959d65d31SAndy Fiddaman 	ACPI_TABLE_HEADER header_le;
61059d65d31SAndy Fiddaman 	/* + 1 is required for the null terminator */
61159d65d31SAndy Fiddaman 	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
61259d65d31SAndy Fiddaman 
61359d65d31SAndy Fiddaman 	assert(table != NULL);
61459d65d31SAndy Fiddaman 	assert(table->len == 0);
61559d65d31SAndy Fiddaman 
61659d65d31SAndy Fiddaman 	memcpy(header_le.Signature, signature, ACPI_NAMESEG_SIZE);
61759d65d31SAndy Fiddaman 	header_le.Length = 0; /* patched by basl_finish */
61859d65d31SAndy Fiddaman 	header_le.Revision = revision;
61959d65d31SAndy Fiddaman 	header_le.Checksum = 0; /* patched by basl_finish */
62059d65d31SAndy Fiddaman 	memcpy(header_le.OemId, "BHYVE ", ACPI_OEM_ID_SIZE);
62159d65d31SAndy Fiddaman 	snprintf(oem_table_id, ACPI_OEM_TABLE_ID_SIZE, "BV%.4s  ", signature);
62259d65d31SAndy Fiddaman 	memcpy(header_le.OemTableId, oem_table_id,
62359d65d31SAndy Fiddaman 	    sizeof(header_le.OemTableId));
62459d65d31SAndy Fiddaman 	header_le.OemRevision = htole32(oem_revision);
62559d65d31SAndy Fiddaman 	memcpy(header_le.AslCompilerId, "BASL", ACPI_NAMESEG_SIZE);
62659d65d31SAndy Fiddaman 	header_le.AslCompilerRevision = htole32(0x20220504);
62759d65d31SAndy Fiddaman 
62859d65d31SAndy Fiddaman 	BASL_EXEC(
62959d65d31SAndy Fiddaman 	    basl_table_append_bytes(table, &header_le, sizeof(header_le)));
63059d65d31SAndy Fiddaman 
63159d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_add_length(table,
63259d65d31SAndy Fiddaman 	    offsetof(ACPI_TABLE_HEADER, Length), sizeof(header_le.Length)));
63359d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_add_checksum(table,
63459d65d31SAndy Fiddaman 	    offsetof(ACPI_TABLE_HEADER, Checksum), 0,
63559d65d31SAndy Fiddaman 	    BASL_TABLE_CHECKSUM_LEN_FULL_TABLE));
63659d65d31SAndy Fiddaman 
63759d65d31SAndy Fiddaman 	return (0);
63859d65d31SAndy Fiddaman }
63959d65d31SAndy Fiddaman 
64059d65d31SAndy Fiddaman int
64159d65d31SAndy Fiddaman basl_table_append_int(struct basl_table *const table, const uint64_t val,
64259d65d31SAndy Fiddaman     const uint8_t size)
64359d65d31SAndy Fiddaman {
64459d65d31SAndy Fiddaman 	char buf[8];
64559d65d31SAndy Fiddaman 
64659d65d31SAndy Fiddaman 	assert(size <= sizeof(val));
64759d65d31SAndy Fiddaman 
64859d65d31SAndy Fiddaman 	basl_le_enc(buf, val, size);
64959d65d31SAndy Fiddaman 	return (basl_table_append_bytes(table, buf, size));
65059d65d31SAndy Fiddaman }
65159d65d31SAndy Fiddaman 
65259d65d31SAndy Fiddaman int
65359d65d31SAndy Fiddaman basl_table_append_length(struct basl_table *const table, const uint8_t size)
65459d65d31SAndy Fiddaman {
65559d65d31SAndy Fiddaman 	assert(table != NULL);
65659d65d31SAndy Fiddaman 	assert(size <= sizeof(table->len));
65759d65d31SAndy Fiddaman 
65859d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_add_length(table, table->len, size));
65959d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_append_int(table, 0, size));
66059d65d31SAndy Fiddaman 
66159d65d31SAndy Fiddaman 	return (0);
66259d65d31SAndy Fiddaman }
66359d65d31SAndy Fiddaman 
66459d65d31SAndy Fiddaman int
66559d65d31SAndy Fiddaman basl_table_append_pointer(struct basl_table *const table,
66659d65d31SAndy Fiddaman     const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint8_t size)
66759d65d31SAndy Fiddaman {
66859d65d31SAndy Fiddaman 	assert(table != NULL);
66959d65d31SAndy Fiddaman 	assert(size == 4 || size == 8);
67059d65d31SAndy Fiddaman 
67159d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_add_pointer(table, src_signature, table->len, size));
67259d65d31SAndy Fiddaman 	BASL_EXEC(basl_table_append_int(table, 0, size));
67359d65d31SAndy Fiddaman 
67459d65d31SAndy Fiddaman 	return (0);
67559d65d31SAndy Fiddaman }
67659d65d31SAndy Fiddaman 
67759d65d31SAndy Fiddaman int
67859d65d31SAndy Fiddaman basl_table_create(struct basl_table **const table, struct vmctx *ctx,
67959d65d31SAndy Fiddaman     const uint8_t *const name, const uint32_t alignment)
68059d65d31SAndy Fiddaman {
68159d65d31SAndy Fiddaman 	struct basl_table *new_table;
68259d65d31SAndy Fiddaman 
68359d65d31SAndy Fiddaman 	assert(table != NULL);
68459d65d31SAndy Fiddaman 
68559d65d31SAndy Fiddaman 	new_table = calloc(1, sizeof(struct basl_table));
68659d65d31SAndy Fiddaman 	if (new_table == NULL) {
68759d65d31SAndy Fiddaman 		warnx("%s: failed to allocate table", __func__);
68859d65d31SAndy Fiddaman 		return (ENOMEM);
68959d65d31SAndy Fiddaman 	}
69059d65d31SAndy Fiddaman 
69159d65d31SAndy Fiddaman 	new_table->ctx = ctx;
69259d65d31SAndy Fiddaman 
69359d65d31SAndy Fiddaman #ifdef	__FreeBSD__
69459d65d31SAndy Fiddaman 	snprintf(new_table->fwcfg_name, sizeof(new_table->fwcfg_name),
69559d65d31SAndy Fiddaman 	    "etc/acpi/%s", name);
69659d65d31SAndy Fiddaman #else
69759d65d31SAndy Fiddaman 	snprintf((char *)new_table->fwcfg_name, sizeof (new_table->fwcfg_name),
69859d65d31SAndy Fiddaman 	    "etc/acpi/%s", name);
69959d65d31SAndy Fiddaman #endif
70059d65d31SAndy Fiddaman 
70159d65d31SAndy Fiddaman 	new_table->alignment = alignment;
70259d65d31SAndy Fiddaman 
70359d65d31SAndy Fiddaman 	STAILQ_INIT(&new_table->checksums);
70459d65d31SAndy Fiddaman 	STAILQ_INIT(&new_table->lengths);
70559d65d31SAndy Fiddaman 	STAILQ_INIT(&new_table->pointers);
70659d65d31SAndy Fiddaman 
70759d65d31SAndy Fiddaman 	STAILQ_INSERT_TAIL(&basl_tables, new_table, chain);
70859d65d31SAndy Fiddaman 
70959d65d31SAndy Fiddaman 	*table = new_table;
71059d65d31SAndy Fiddaman 
71159d65d31SAndy Fiddaman 	return (0);
71259d65d31SAndy Fiddaman }
713*32640292SAndy Fiddaman 
714*32640292SAndy Fiddaman int
715*32640292SAndy Fiddaman basl_table_register_to_rsdt(struct basl_table *table)
716*32640292SAndy Fiddaman {
717*32640292SAndy Fiddaman 	const ACPI_TABLE_HEADER *header;
718*32640292SAndy Fiddaman 
719*32640292SAndy Fiddaman 	assert(table != NULL);
720*32640292SAndy Fiddaman 
721*32640292SAndy Fiddaman 	header = (const ACPI_TABLE_HEADER *)table->data;
722*32640292SAndy Fiddaman 
723*32640292SAndy Fiddaman #ifdef	__FreeBSD__
724*32640292SAndy Fiddaman 	BASL_EXEC(basl_table_append_pointer(rsdt, header->Signature,
725*32640292SAndy Fiddaman 	    ACPI_RSDT_ENTRY_SIZE));
726*32640292SAndy Fiddaman 	BASL_EXEC(basl_table_append_pointer(xsdt, header->Signature,
727*32640292SAndy Fiddaman 	    ACPI_XSDT_ENTRY_SIZE));
728*32640292SAndy Fiddaman #else
729*32640292SAndy Fiddaman 	BASL_EXEC(basl_table_append_pointer(rsdt, (uint8_t *)header->Signature,
730*32640292SAndy Fiddaman 	    ACPI_RSDT_ENTRY_SIZE));
731*32640292SAndy Fiddaman 	BASL_EXEC(basl_table_append_pointer(xsdt, (uint8_t *)header->Signature,
732*32640292SAndy Fiddaman 	    ACPI_XSDT_ENTRY_SIZE));
733*32640292SAndy Fiddaman #endif
734*32640292SAndy Fiddaman 
735*32640292SAndy Fiddaman 	return (0);
736*32640292SAndy Fiddaman }
737