blob: 26bf0cb8d30d0073ad5a085c0eaae00cdcaff4c7 [file] [log] [blame]
Simon Glass94ba15a2021-12-01 09:02:50 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Write base ACPI tables
4 *
5 * Copyright 2021 Google LLC
6 */
7
Simon Glasseacb6d02021-12-01 09:02:52 -07008#define LOG_CATEGORY LOGC_ACPI
9
Simon Glass94ba15a2021-12-01 09:02:50 -070010#include <common.h>
11#include <acpi/acpi_table.h>
12#include <dm/acpi.h>
13#include <mapmem.h>
14#include <tables_csum.h>
Heinrich Schuchardtc7b31a92023-11-13 00:53:56 +010015#include <linux/sizes.h>
Simon Glass94ba15a2021-12-01 09:02:50 -070016
17void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt,
18 struct acpi_xsdt *xsdt)
19{
20 memset(rsdp, 0, sizeof(struct acpi_rsdp));
21
22 memcpy(rsdp->signature, RSDP_SIG, 8);
23 memcpy(rsdp->oem_id, OEM_ID, 6);
24
Heinrich Schuchardtc7b31a92023-11-13 00:53:56 +010025 if (rsdt)
26 rsdp->rsdt_address = map_to_sysmem(rsdt);
Simon Glass94ba15a2021-12-01 09:02:50 -070027
Heinrich Schuchardtc7b31a92023-11-13 00:53:56 +010028 if (xsdt)
29 rsdp->xsdt_address = map_to_sysmem(xsdt);
30
31 rsdp->length = sizeof(struct acpi_rsdp);
Simon Glass94ba15a2021-12-01 09:02:50 -070032 rsdp->revision = ACPI_RSDP_REV_ACPI_2_0;
33
34 /* Calculate checksums */
35 rsdp->checksum = table_compute_checksum(rsdp, 20);
36 rsdp->ext_checksum = table_compute_checksum(rsdp,
37 sizeof(struct acpi_rsdp));
38}
39
40static void acpi_write_rsdt(struct acpi_rsdt *rsdt)
41{
42 struct acpi_table_header *header = &rsdt->header;
43
44 /* Fill out header fields */
45 acpi_fill_header(header, "RSDT");
46 header->length = sizeof(struct acpi_rsdt);
47 header->revision = 1;
48
49 /* Entries are filled in later, we come with an empty set */
50
51 /* Fix checksum */
52 header->checksum = table_compute_checksum(rsdt,
53 sizeof(struct acpi_rsdt));
54}
55
56static void acpi_write_xsdt(struct acpi_xsdt *xsdt)
57{
58 struct acpi_table_header *header = &xsdt->header;
59
60 /* Fill out header fields */
61 acpi_fill_header(header, "XSDT");
62 header->length = sizeof(struct acpi_xsdt);
63 header->revision = 1;
64
65 /* Entries are filled in later, we come with an empty set */
66
67 /* Fix checksum */
68 header->checksum = table_compute_checksum(xsdt,
69 sizeof(struct acpi_xsdt));
70}
71
72static int acpi_write_base(struct acpi_ctx *ctx,
73 const struct acpi_writer *entry)
74{
Heinrich Schuchardtc7b31a92023-11-13 00:53:56 +010075 /* We need at least an RSDP and an XSDT Table */
Simon Glass94ba15a2021-12-01 09:02:50 -070076 ctx->rsdp = ctx->current;
77 acpi_inc_align(ctx, sizeof(struct acpi_rsdp));
Heinrich Schuchardtc7b31a92023-11-13 00:53:56 +010078 if (map_to_sysmem(ctx->current) < SZ_4G - SZ_64K) {
79 ctx->rsdt = ctx->current;
80 acpi_inc_align(ctx, sizeof(struct acpi_rsdt));
81 } else {
82 ctx->rsdt = 0;
83 }
Simon Glass94ba15a2021-12-01 09:02:50 -070084 ctx->xsdt = ctx->current;
85 acpi_inc_align(ctx, sizeof(struct acpi_xsdt));
86
87 /* clear all table memory */
88 memset(ctx->base, '\0', ctx->current - ctx->base);
89
90 acpi_write_rsdp(ctx->rsdp, ctx->rsdt, ctx->xsdt);
Heinrich Schuchardtc7b31a92023-11-13 00:53:56 +010091 if (ctx->rsdt)
92 acpi_write_rsdt(ctx->rsdt);
Simon Glass94ba15a2021-12-01 09:02:50 -070093 acpi_write_xsdt(ctx->xsdt);
94
95 return 0;
96}
97/*
98 * Per ACPI spec, the FACS table address must be aligned to a 64-byte boundary
99 * (Windows checks this, but Linux does not).
100 *
101 * Use the '0' prefix to put this one first
102 */
103ACPI_WRITER(0base, NULL, acpi_write_base, ACPIWF_ALIGN64);