]>
Commit | Line | Data |
---|---|---|
94ba15a3 SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Write base ACPI tables | |
4 | * | |
5 | * Copyright 2021 Google LLC | |
6 | */ | |
7 | ||
eacb6d0b SG |
8 | #define LOG_CATEGORY LOGC_ACPI |
9 | ||
94ba15a3 SG |
10 | #include <acpi/acpi_table.h> |
11 | #include <dm/acpi.h> | |
12 | #include <mapmem.h> | |
13 | #include <tables_csum.h> | |
c7b31a9a | 14 | #include <linux/sizes.h> |
467382ca TR |
15 | #include <linux/errno.h> |
16 | #include <linux/string.h> | |
94ba15a3 SG |
17 | |
18 | void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, | |
19 | struct acpi_xsdt *xsdt) | |
20 | { | |
21 | memset(rsdp, 0, sizeof(struct acpi_rsdp)); | |
22 | ||
23 | memcpy(rsdp->signature, RSDP_SIG, 8); | |
24 | memcpy(rsdp->oem_id, OEM_ID, 6); | |
25 | ||
c7b31a9a | 26 | if (rsdt) |
a8efebe7 | 27 | rsdp->rsdt_address = nomap_to_sysmem(rsdt); |
c7b31a9a HS |
28 | |
29 | if (xsdt) | |
a8efebe7 | 30 | rsdp->xsdt_address = nomap_to_sysmem(xsdt); |
94ba15a3 | 31 | |
c7b31a9a | 32 | rsdp->length = sizeof(struct acpi_rsdp); |
94ba15a3 SG |
33 | rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; |
34 | ||
35 | /* Calculate checksums */ | |
36 | rsdp->checksum = table_compute_checksum(rsdp, 20); | |
37 | rsdp->ext_checksum = table_compute_checksum(rsdp, | |
38 | sizeof(struct acpi_rsdp)); | |
39 | } | |
40 | ||
41 | static void acpi_write_rsdt(struct acpi_rsdt *rsdt) | |
42 | { | |
43 | struct acpi_table_header *header = &rsdt->header; | |
44 | ||
45 | /* Fill out header fields */ | |
46 | acpi_fill_header(header, "RSDT"); | |
47 | header->length = sizeof(struct acpi_rsdt); | |
48 | header->revision = 1; | |
49 | ||
50 | /* Entries are filled in later, we come with an empty set */ | |
51 | ||
52 | /* Fix checksum */ | |
53 | header->checksum = table_compute_checksum(rsdt, | |
54 | sizeof(struct acpi_rsdt)); | |
55 | } | |
56 | ||
57 | static void acpi_write_xsdt(struct acpi_xsdt *xsdt) | |
58 | { | |
59 | struct acpi_table_header *header = &xsdt->header; | |
60 | ||
61 | /* Fill out header fields */ | |
62 | acpi_fill_header(header, "XSDT"); | |
63 | header->length = sizeof(struct acpi_xsdt); | |
64 | header->revision = 1; | |
65 | ||
66 | /* Entries are filled in later, we come with an empty set */ | |
67 | ||
68 | /* Fix checksum */ | |
69 | header->checksum = table_compute_checksum(xsdt, | |
70 | sizeof(struct acpi_xsdt)); | |
71 | } | |
72 | ||
73 | static int acpi_write_base(struct acpi_ctx *ctx, | |
74 | const struct acpi_writer *entry) | |
75 | { | |
c7b31a9a | 76 | /* We need at least an RSDP and an XSDT Table */ |
94ba15a3 SG |
77 | ctx->rsdp = ctx->current; |
78 | acpi_inc_align(ctx, sizeof(struct acpi_rsdp)); | |
c7b31a9a HS |
79 | if (map_to_sysmem(ctx->current) < SZ_4G - SZ_64K) { |
80 | ctx->rsdt = ctx->current; | |
81 | acpi_inc_align(ctx, sizeof(struct acpi_rsdt)); | |
82 | } else { | |
83 | ctx->rsdt = 0; | |
84 | } | |
94ba15a3 SG |
85 | ctx->xsdt = ctx->current; |
86 | acpi_inc_align(ctx, sizeof(struct acpi_xsdt)); | |
87 | ||
88 | /* clear all table memory */ | |
89 | memset(ctx->base, '\0', ctx->current - ctx->base); | |
90 | ||
91 | acpi_write_rsdp(ctx->rsdp, ctx->rsdt, ctx->xsdt); | |
c7b31a9a HS |
92 | if (ctx->rsdt) |
93 | acpi_write_rsdt(ctx->rsdt); | |
94ba15a3 SG |
94 | acpi_write_xsdt(ctx->xsdt); |
95 | ||
96 | return 0; | |
97 | } | |
98 | /* | |
99 | * Per ACPI spec, the FACS table address must be aligned to a 64-byte boundary | |
100 | * (Windows checks this, but Linux does not). | |
101 | * | |
102 | * Use the '0' prefix to put this one first | |
103 | */ | |
104 | ACPI_WRITER(0base, NULL, acpi_write_base, ACPIWF_ALIGN64); |