xref: /illumos-gate/usr/src/cmd/bhyve/basl.c (revision 32640292)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG
5  */
6 
7 #include <sys/param.h>
8 #include <sys/endian.h>
9 #include <sys/errno.h>
10 #include <sys/queue.h>
11 #include <sys/stat.h>
12 
13 #include <machine/vmm.h>
14 
15 #include <assert.h>
16 #include <err.h>
17 #include <libutil.h>
18 #include <stddef.h>
19 #include <stdio.h>
20 #include <vmmapi.h>
21 
22 #ifndef	__FreeBSD__
23 #include "hexdump.h"
24 #endif
25 
26 #include "basl.h"
27 #include "config.h"
28 #include "qemu_loader.h"
29 
30 struct basl_table_checksum {
31 	STAILQ_ENTRY(basl_table_checksum) chain;
32 	uint32_t off;
33 	uint32_t start;
34 	uint32_t len;
35 };
36 
37 struct basl_table_length {
38 	STAILQ_ENTRY(basl_table_length) chain;
39 	uint32_t off;
40 	uint8_t size;
41 };
42 
43 struct basl_table_pointer {
44 	STAILQ_ENTRY(basl_table_pointer) chain;
45 	uint8_t src_signature[ACPI_NAMESEG_SIZE];
46 	uint32_t off;
47 	uint8_t size;
48 };
49 
50 struct basl_table {
51 	STAILQ_ENTRY(basl_table) chain;
52 	struct vmctx *ctx;
53 	uint8_t fwcfg_name[QEMU_FWCFG_MAX_NAME];
54 	void *data;
55 	uint32_t len;
56 	uint32_t off;
57 	uint32_t alignment;
58 	STAILQ_HEAD(basl_table_checksum_list, basl_table_checksum) checksums;
59 	STAILQ_HEAD(basl_table_length_list, basl_table_length) lengths;
60 	STAILQ_HEAD(basl_table_pointer_list, basl_table_pointer) pointers;
61 };
62 static STAILQ_HEAD(basl_table_list, basl_table) basl_tables = STAILQ_HEAD_INITIALIZER(
63     basl_tables);
64 
65 static struct qemu_loader *basl_loader;
66 static struct basl_table *rsdt;
67 static struct basl_table *xsdt;
68 static bool load_into_memory;
69 
70 static __inline uint64_t
basl_le_dec(void * pp,size_t len)71 basl_le_dec(void *pp, size_t len)
72 {
73 	assert(len <= 8);
74 
75 	switch (len) {
76 	case 1:
77 		return ((uint8_t *)pp)[0];
78 	case 2:
79 		return le16dec(pp);
80 	case 4:
81 		return le32dec(pp);
82 	case 8:
83 		return le64dec(pp);
84 	}
85 
86 	return 0;
87 }
88 
89 static __inline void
basl_le_enc(void * pp,uint64_t val,size_t len)90 basl_le_enc(void *pp, uint64_t val, size_t len)
91 {
92 	char buf[8];
93 
94 	assert(len <= 8);
95 
96 	le64enc(buf, val);
97 	memcpy(pp, buf, len);
98 }
99 
100 static int
basl_dump_table(const struct basl_table * const table,const bool mem)101 basl_dump_table(const struct basl_table *const table, const bool mem)
102 {
103 	const ACPI_TABLE_HEADER *const header = table->data;
104 	const uint8_t *data;
105 
106 	if (!mem) {
107 		data = table->data;
108 	} else {
109 		data = vm_map_gpa(table->ctx, BHYVE_ACPI_BASE + table->off,
110 		    table->len);
111 		if (data == NULL) {
112 			return (ENOMEM);
113 		}
114 	}
115 
116 	printf("%.4s @ %8x (%s)\n", header->Signature,
117 	    BHYVE_ACPI_BASE + table->off, mem ? "Memory" : "FwCfg");
118 	hexdump(data, table->len, NULL, 0);
119 
120 	return (0);
121 }
122 
123 static int __unused
basl_dump(const bool mem)124 basl_dump(const bool mem)
125 {
126 	struct basl_table *table;
127 
128 	STAILQ_FOREACH(table, &basl_tables, chain) {
129 		BASL_EXEC(basl_dump_table(table, mem));
130 	}
131 
132 	return (0);
133 }
134 
135 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)136 basl_fill_gas(ACPI_GENERIC_ADDRESS *const gas, const uint8_t space_id,
137     const uint8_t bit_width, const uint8_t bit_offset,
138     const uint8_t access_width, const uint64_t address)
139 {
140 	assert(gas != NULL);
141 
142 	gas->SpaceId = space_id;
143 	gas->BitWidth = bit_width;
144 	gas->BitOffset = bit_offset;
145 	gas->AccessWidth = access_width;
146 	gas->Address = htole64(address);
147 }
148 
149 static int
basl_finish_install_guest_tables(struct basl_table * const table,uint32_t * const off)150 basl_finish_install_guest_tables(struct basl_table *const table, uint32_t *const off)
151 {
152 	void *gva;
153 
154 	table->off = roundup2(*off, table->alignment);
155 	*off = table->off + table->len;
156 	if (*off <= table->off) {
157 		warnx("%s: invalid table length 0x%8x @ offset 0x%8x", __func__,
158 		    table->len, table->off);
159 		return (EFAULT);
160 	}
161 
162 	/* Cause guest BIOS to copy the ACPI table into guest memory. */
163 #ifdef	__FreeBSD__
164 	BASL_EXEC(
165 	    qemu_fwcfg_add_file(table->fwcfg_name, table->len, table->data));
166 #else
167 	BASL_EXEC(
168 	    qemu_fwcfg_add_file((const char *)table->fwcfg_name,
169 	    table->len, table->data));
170 #endif
171 	BASL_EXEC(qemu_loader_alloc(basl_loader, table->fwcfg_name,
172 	    table->alignment, QEMU_LOADER_ALLOC_HIGH));
173 
174 	if (!load_into_memory) {
175 		return (0);
176 	}
177 
178 	/*
179 	 * Install ACPI tables directly in guest memory for use by guests which
180 	 * do not boot via EFI. EFI ROMs provide a pointer to the firmware
181 	 * generated ACPI tables instead, but it doesn't hurt to install the
182 	 * tables always.
183 	 */
184 	gva = vm_map_gpa(table->ctx, BHYVE_ACPI_BASE + table->off, table->len);
185 	if (gva == NULL) {
186 		warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]", __func__,
187 		    (uint64_t)BHYVE_ACPI_BASE + table->off,
188 		    (uint64_t)BHYVE_ACPI_BASE + table->off + table->len);
189 		return (ENOMEM);
190 	}
191 	memcpy(gva, table->data, table->len);
192 
193 	return (0);
194 }
195 
196 static int
basl_finish_patch_checksums(struct basl_table * const table)197 basl_finish_patch_checksums(struct basl_table *const table)
198 {
199 	struct basl_table_checksum *checksum;
200 
201 	STAILQ_FOREACH(checksum, &table->checksums, chain) {
202 		uint8_t *gva, *checksum_gva;
203 		uint64_t gpa;
204 		uint32_t len;
205 		uint8_t sum;
206 
207 		len = checksum->len;
208 		if (len == BASL_TABLE_CHECKSUM_LEN_FULL_TABLE) {
209 			len = table->len;
210 		}
211 
212 		assert(checksum->off < table->len);
213 		assert(checksum->start < table->len);
214 		assert(checksum->start + len <= table->len);
215 
216 		/* Cause guest BIOS to patch the checksum. */
217 		BASL_EXEC(qemu_loader_add_checksum(basl_loader,
218 		    table->fwcfg_name, checksum->off, checksum->start, len));
219 
220 		if (!load_into_memory) {
221 			continue;
222 		}
223 
224 		/*
225 		 * Install ACPI tables directly in guest memory for use by
226 		 * guests which do not boot via EFI. EFI ROMs provide a pointer
227 		 * to the firmware generated ACPI tables instead, but it doesn't
228 		 * hurt to install the tables always.
229 		 */
230 		gpa = BHYVE_ACPI_BASE + table->off + checksum->start;
231 		if ((gpa < BHYVE_ACPI_BASE) ||
232 		    (gpa < BHYVE_ACPI_BASE + table->off)) {
233 			warnx("%s: invalid gpa (off 0x%8x start 0x%8x)",
234 			    __func__, table->off, checksum->start);
235 			return (EFAULT);
236 		}
237 
238 		gva = vm_map_gpa(table->ctx, gpa, len);
239 		if (gva == NULL) {
240 			warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
241 			    __func__, gpa, gpa + len);
242 			return (ENOMEM);
243 		}
244 
245 		checksum_gva = gva + checksum->off;
246 		if (checksum_gva < gva) {
247 			warnx("%s: invalid checksum offset 0x%8x", __func__,
248 			    checksum->off);
249 			return (EFAULT);
250 		}
251 
252 		sum = 0;
253 		for (uint32_t i = 0; i < len; ++i) {
254 			sum += *(gva + i);
255 		}
256 		*checksum_gva = -sum;
257 	}
258 
259 	return (0);
260 }
261 
262 static struct basl_table *
basl_get_table_by_signature(const uint8_t signature[ACPI_NAMESEG_SIZE])263 basl_get_table_by_signature(const uint8_t signature[ACPI_NAMESEG_SIZE])
264 {
265 	struct basl_table *table;
266 
267 	STAILQ_FOREACH(table, &basl_tables, chain) {
268 		const ACPI_TABLE_HEADER *const header =
269 		    (const ACPI_TABLE_HEADER *)table->data;
270 
271 #ifdef	__FreeBSD__
272 		if (strncmp(header->Signature, signature,
273 			sizeof(header->Signature)) == 0) {
274 			return (table);
275 #else
276 		if (strncmp(header->Signature, (char *)signature,
277 			sizeof(header->Signature)) == 0) {
278 			return (table);
279 #endif
280 		}
281 	}
282 
283 	warnx("%s: %.4s not found", __func__, signature);
284 	return (NULL);
285 }
286 
287 static int
288 basl_finish_patch_pointers(struct basl_table *const table)
289 {
290 	struct basl_table_pointer *pointer;
291 
292 	STAILQ_FOREACH(pointer, &table->pointers, chain) {
293 		const struct basl_table *src_table;
294 		uint8_t *gva;
295 		uint64_t gpa, val;
296 
297 		assert(pointer->off < table->len);
298 		assert(pointer->off + pointer->size <= table->len);
299 
300 		src_table = basl_get_table_by_signature(pointer->src_signature);
301 		if (src_table == NULL) {
302 			warnx("%s: could not find ACPI table %.4s", __func__,
303 			    pointer->src_signature);
304 			return (EFAULT);
305 		}
306 
307 		/* Cause guest BIOS to patch the pointer. */
308 		BASL_EXEC(
309 		    qemu_loader_add_pointer(basl_loader, table->fwcfg_name,
310 			src_table->fwcfg_name, pointer->off, pointer->size));
311 
312 		if (!load_into_memory) {
313 			continue;
314 		}
315 
316 		/*
317 		 * Install ACPI tables directly in guest memory for use by
318 		 * guests which do not boot via EFI. EFI ROMs provide a pointer
319 		 * to the firmware generated ACPI tables instead, but it doesn't
320 		 * hurt to install the tables always.
321 		 */
322 		gpa = BHYVE_ACPI_BASE + table->off;
323 		if (gpa < BHYVE_ACPI_BASE) {
324 			warnx("%s: table offset of 0x%8x is too large",
325 			    __func__, table->off);
326 			return (EFAULT);
327 		}
328 
329 		gva = vm_map_gpa(table->ctx, gpa, table->len);
330 		if (gva == NULL) {
331 			warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
332 			    __func__, gpa, gpa + table->len);
333 			return (ENOMEM);
334 		}
335 
336 		val = basl_le_dec(gva + pointer->off, pointer->size);
337 		val += BHYVE_ACPI_BASE + src_table->off;
338 		basl_le_enc(gva + pointer->off, val, pointer->size);
339 	}
340 
341 	return (0);
342 }
343 
344 static int
345 basl_finish_set_length(struct basl_table *const table)
346 {
347 	struct basl_table_length *length;
348 
349 	STAILQ_FOREACH(length, &table->lengths, chain) {
350 		assert(length->off < table->len);
351 		assert(length->off + length->size <= table->len);
352 
353 		basl_le_enc((uint8_t *)table->data + length->off, table->len,
354 		    length->size);
355 	}
356 
357 	return (0);
358 }
359 
360 int
361 basl_finish(void)
362 {
363 	struct basl_table *table;
364 	uint32_t off = 0;
365 
366 	if (STAILQ_EMPTY(&basl_tables)) {
367 		warnx("%s: no ACPI tables found", __func__);
368 		return (EINVAL);
369 	}
370 
371 	/*
372 	 * If we install ACPI tables by FwCfg and by memory, Windows will use
373 	 * the tables from memory. This can cause issues when using advanced
374 	 * features like a TPM log because we aren't able to patch the memory
375 	 * tables accordingly.
376 	 */
377 	load_into_memory = get_config_bool_default("acpi_tables_in_memory",
378 	    true);
379 
380 	/*
381 	 * We have to install all tables before we can patch them. Therefore,
382 	 * use two loops. The first one installs all tables and the second one
383 	 * patches them.
384 	 */
385 	STAILQ_FOREACH(table, &basl_tables, chain) {
386 		BASL_EXEC(basl_finish_set_length(table));
387 		BASL_EXEC(basl_finish_install_guest_tables(table, &off));
388 	}
389 	STAILQ_FOREACH(table, &basl_tables, chain) {
390 		BASL_EXEC(basl_finish_patch_pointers(table));
391 
392 		/*
393 		 * Calculate the checksum as last step!
394 		 */
395 		BASL_EXEC(basl_finish_patch_checksums(table));
396 	}
397 	BASL_EXEC(qemu_loader_finish(basl_loader));
398 
399 	return (0);
400 }
401 
402 static int
403 basl_init_rsdt(struct vmctx *const ctx)
404 {
405 	BASL_EXEC(
406 	    basl_table_create(&rsdt, ctx, ACPI_SIG_RSDT, BASL_TABLE_ALIGNMENT));
407 
408 	/* Header */
409 	BASL_EXEC(basl_table_append_header(rsdt, ACPI_SIG_RSDT, 1, 1));
410 	/* Pointers (added by basl_table_register_to_rsdt) */
411 
412 	return (0);
413 }
414 
415 static int
416 basl_init_xsdt(struct vmctx *const ctx)
417 {
418 	BASL_EXEC(
419 	    basl_table_create(&xsdt, ctx, ACPI_SIG_XSDT, BASL_TABLE_ALIGNMENT));
420 
421 	/* Header */
422 	BASL_EXEC(basl_table_append_header(xsdt, ACPI_SIG_XSDT, 1, 1));
423 	/* Pointers (added by basl_table_register_to_rsdt) */
424 
425 	return (0);
426 }
427 
428 int
429 basl_init(struct vmctx *const ctx)
430 {
431 	BASL_EXEC(basl_init_rsdt(ctx));
432 	BASL_EXEC(basl_init_xsdt(ctx));
433 #ifdef	__FreeBSD__
434 	BASL_EXEC(
435 	    qemu_loader_create(&basl_loader, QEMU_FWCFG_FILE_TABLE_LOADER));
436 #else
437 	BASL_EXEC(
438 	    qemu_loader_create(&basl_loader,
439 	    (uint8_t *)QEMU_FWCFG_FILE_TABLE_LOADER));
440 #endif
441 
442 	return (0);
443 }
444 
445 int
446 basl_table_add_checksum(struct basl_table *const table, const uint32_t off,
447     const uint32_t start, const uint32_t len)
448 {
449 	struct basl_table_checksum *checksum;
450 
451 	assert(table != NULL);
452 
453 	checksum = calloc(1, sizeof(struct basl_table_checksum));
454 	if (checksum == NULL) {
455 		warnx("%s: failed to allocate checksum", __func__);
456 		return (ENOMEM);
457 	}
458 
459 	checksum->off = off;
460 	checksum->start = start;
461 	checksum->len = len;
462 
463 	STAILQ_INSERT_TAIL(&table->checksums, checksum, chain);
464 
465 	return (0);
466 }
467 
468 int
469 basl_table_add_length(struct basl_table *const table, const uint32_t off,
470     const uint8_t size)
471 {
472 	struct basl_table_length *length;
473 
474 	assert(table != NULL);
475 	assert(size == 4 || size == 8);
476 
477 	length = calloc(1, sizeof(struct basl_table_length));
478 	if (length == NULL) {
479 		warnx("%s: failed to allocate length", __func__);
480 		return (ENOMEM);
481 	}
482 
483 	length->off = off;
484 	length->size = size;
485 
486 	STAILQ_INSERT_TAIL(&table->lengths, length, chain);
487 
488 	return (0);
489 }
490 
491 int
492 basl_table_add_pointer(struct basl_table *const table,
493     const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint32_t off,
494     const uint8_t size)
495 {
496 	struct basl_table_pointer *pointer;
497 
498 	assert(table != NULL);
499 	assert(size == 4 || size == 8);
500 
501 	pointer = calloc(1, sizeof(struct basl_table_pointer));
502 	if (pointer == NULL) {
503 		warnx("%s: failed to allocate pointer", __func__);
504 		return (ENOMEM);
505 	}
506 
507 	memcpy(pointer->src_signature, src_signature,
508 	    sizeof(pointer->src_signature));
509 	pointer->off = off;
510 	pointer->size = size;
511 
512 	STAILQ_INSERT_TAIL(&table->pointers, pointer, chain);
513 
514 	return (0);
515 }
516 
517 int
518 basl_table_append_bytes(struct basl_table *const table, const void *const bytes,
519     const uint32_t len)
520 {
521 	void *end;
522 
523 	assert(table != NULL);
524 	assert(bytes != NULL);
525 
526 	if (table->len + len <= table->len) {
527 		warnx("%s: table too large (table->len 0x%8x len 0x%8x)",
528 		    __func__, table->len, len);
529 		return (EFAULT);
530 	}
531 
532 	table->data = reallocf(table->data, table->len + len);
533 	if (table->data == NULL) {
534 		warnx("%s: failed to realloc table to length 0x%8x", __func__,
535 		    table->len + len);
536 		table->len = 0;
537 		return (ENOMEM);
538 	}
539 
540 	end = (uint8_t *)table->data + table->len;
541 	table->len += len;
542 
543 	memcpy(end, bytes, len);
544 
545 	return (0);
546 }
547 
548 int
549 basl_table_append_checksum(struct basl_table *const table, const uint32_t start,
550     const uint32_t len)
551 {
552 	assert(table != NULL);
553 
554 	BASL_EXEC(basl_table_add_checksum(table, table->len, start, len));
555 	BASL_EXEC(basl_table_append_int(table, 0, 1));
556 
557 	return (0);
558 }
559 
560 int
561 basl_table_append_content(struct basl_table *table, void *data, uint32_t len)
562 {
563 	assert(data != NULL);
564 	assert(len >= sizeof(ACPI_TABLE_HEADER));
565 
566 	return (basl_table_append_bytes(table,
567 	    (void *)((uintptr_t)(data) + sizeof(ACPI_TABLE_HEADER)),
568 	    len - sizeof(ACPI_TABLE_HEADER)));
569 }
570 
571 int
572 basl_table_append_fwcfg(struct basl_table *const table,
573     const uint8_t *fwcfg_name, const uint32_t alignment, const uint8_t size)
574 {
575 	assert(table != NULL);
576 	assert(fwcfg_name != NULL);
577 	assert(size <= sizeof(uint64_t));
578 
579 	BASL_EXEC(qemu_loader_alloc(basl_loader, fwcfg_name, alignment,
580 	    QEMU_LOADER_ALLOC_HIGH));
581 	BASL_EXEC(qemu_loader_add_pointer(basl_loader, table->fwcfg_name,
582 	    fwcfg_name, table->len, size));
583 	BASL_EXEC(basl_table_append_int(table, 0, size));
584 
585 	return (0);
586 }
587 
588 int
589 basl_table_append_gas(struct basl_table *const table, const uint8_t space_id,
590     const uint8_t bit_width, const uint8_t bit_offset,
591     const uint8_t access_width, const uint64_t address)
592 {
593 	ACPI_GENERIC_ADDRESS gas_le = {
594 		.SpaceId = space_id,
595 		.BitWidth = bit_width,
596 		.BitOffset = bit_offset,
597 		.AccessWidth = access_width,
598 		.Address = htole64(address),
599 	};
600 
601 	return (basl_table_append_bytes(table, &gas_le, sizeof(gas_le)));
602 }
603 
604 int
605 basl_table_append_header(struct basl_table *const table,
606     const uint8_t signature[ACPI_NAMESEG_SIZE], const uint8_t revision,
607     const uint32_t oem_revision)
608 {
609 	ACPI_TABLE_HEADER header_le;
610 	/* + 1 is required for the null terminator */
611 	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
612 
613 	assert(table != NULL);
614 	assert(table->len == 0);
615 
616 	memcpy(header_le.Signature, signature, ACPI_NAMESEG_SIZE);
617 	header_le.Length = 0; /* patched by basl_finish */
618 	header_le.Revision = revision;
619 	header_le.Checksum = 0; /* patched by basl_finish */
620 	memcpy(header_le.OemId, "BHYVE ", ACPI_OEM_ID_SIZE);
621 	snprintf(oem_table_id, ACPI_OEM_TABLE_ID_SIZE, "BV%.4s  ", signature);
622 	memcpy(header_le.OemTableId, oem_table_id,
623 	    sizeof(header_le.OemTableId));
624 	header_le.OemRevision = htole32(oem_revision);
625 	memcpy(header_le.AslCompilerId, "BASL", ACPI_NAMESEG_SIZE);
626 	header_le.AslCompilerRevision = htole32(0x20220504);
627 
628 	BASL_EXEC(
629 	    basl_table_append_bytes(table, &header_le, sizeof(header_le)));
630 
631 	BASL_EXEC(basl_table_add_length(table,
632 	    offsetof(ACPI_TABLE_HEADER, Length), sizeof(header_le.Length)));
633 	BASL_EXEC(basl_table_add_checksum(table,
634 	    offsetof(ACPI_TABLE_HEADER, Checksum), 0,
635 	    BASL_TABLE_CHECKSUM_LEN_FULL_TABLE));
636 
637 	return (0);
638 }
639 
640 int
641 basl_table_append_int(struct basl_table *const table, const uint64_t val,
642     const uint8_t size)
643 {
644 	char buf[8];
645 
646 	assert(size <= sizeof(val));
647 
648 	basl_le_enc(buf, val, size);
649 	return (basl_table_append_bytes(table, buf, size));
650 }
651 
652 int
653 basl_table_append_length(struct basl_table *const table, const uint8_t size)
654 {
655 	assert(table != NULL);
656 	assert(size <= sizeof(table->len));
657 
658 	BASL_EXEC(basl_table_add_length(table, table->len, size));
659 	BASL_EXEC(basl_table_append_int(table, 0, size));
660 
661 	return (0);
662 }
663 
664 int
665 basl_table_append_pointer(struct basl_table *const table,
666     const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint8_t size)
667 {
668 	assert(table != NULL);
669 	assert(size == 4 || size == 8);
670 
671 	BASL_EXEC(basl_table_add_pointer(table, src_signature, table->len, size));
672 	BASL_EXEC(basl_table_append_int(table, 0, size));
673 
674 	return (0);
675 }
676 
677 int
678 basl_table_create(struct basl_table **const table, struct vmctx *ctx,
679     const uint8_t *const name, const uint32_t alignment)
680 {
681 	struct basl_table *new_table;
682 
683 	assert(table != NULL);
684 
685 	new_table = calloc(1, sizeof(struct basl_table));
686 	if (new_table == NULL) {
687 		warnx("%s: failed to allocate table", __func__);
688 		return (ENOMEM);
689 	}
690 
691 	new_table->ctx = ctx;
692 
693 #ifdef	__FreeBSD__
694 	snprintf(new_table->fwcfg_name, sizeof(new_table->fwcfg_name),
695 	    "etc/acpi/%s", name);
696 #else
697 	snprintf((char *)new_table->fwcfg_name, sizeof (new_table->fwcfg_name),
698 	    "etc/acpi/%s", name);
699 #endif
700 
701 	new_table->alignment = alignment;
702 
703 	STAILQ_INIT(&new_table->checksums);
704 	STAILQ_INIT(&new_table->lengths);
705 	STAILQ_INIT(&new_table->pointers);
706 
707 	STAILQ_INSERT_TAIL(&basl_tables, new_table, chain);
708 
709 	*table = new_table;
710 
711 	return (0);
712 }
713 
714 int
715 basl_table_register_to_rsdt(struct basl_table *table)
716 {
717 	const ACPI_TABLE_HEADER *header;
718 
719 	assert(table != NULL);
720 
721 	header = (const ACPI_TABLE_HEADER *)table->data;
722 
723 #ifdef	__FreeBSD__
724 	BASL_EXEC(basl_table_append_pointer(rsdt, header->Signature,
725 	    ACPI_RSDT_ENTRY_SIZE));
726 	BASL_EXEC(basl_table_append_pointer(xsdt, header->Signature,
727 	    ACPI_XSDT_ENTRY_SIZE));
728 #else
729 	BASL_EXEC(basl_table_append_pointer(rsdt, (uint8_t *)header->Signature,
730 	    ACPI_RSDT_ENTRY_SIZE));
731 	BASL_EXEC(basl_table_append_pointer(xsdt, (uint8_t *)header->Signature,
732 	    ACPI_XSDT_ENTRY_SIZE));
733 #endif
734 
735 	return (0);
736 }
737