Merge tag 'mmc-2021-4-6' of https://source.denx.de/u-boot/custodians/u-boot-mmc
[platform/kernel/u-boot.git] / cmd / acpi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 #include <common.h>
7 #include <command.h>
8 #include <mapmem.h>
9 #include <acpi/acpi_table.h>
10 #include <asm/acpi_table.h>
11 #include <asm/global_data.h>
12 #include <dm/acpi.h>
13
14 DECLARE_GLOBAL_DATA_PTR;
15
16 /**
17  * dump_hdr() - Dump an ACPI header
18  *
19  * If the header is for FACS then it shows the revision information as well
20  *
21  * @hdr: ACPI header to dump
22  */
23 static void dump_hdr(struct acpi_table_header *hdr)
24 {
25         bool has_hdr = memcmp(hdr->signature, "FACS", ACPI_NAME_LEN);
26
27         printf("%.*s %08lx %06x", ACPI_NAME_LEN, hdr->signature,
28                (ulong)map_to_sysmem(hdr), hdr->length);
29         if (has_hdr) {
30                 printf(" (v%02d %.6s %.8s %x %.4s %x)\n", hdr->revision,
31                        hdr->oem_id, hdr->oem_table_id, hdr->oem_revision,
32                        hdr->aslc_id, hdr->aslc_revision);
33         } else {
34                 printf("\n");
35         }
36 }
37
38 /**
39  * find_table() - Look up an ACPI table
40  *
41  * @sig: Signature of table (4 characters, upper case)
42  * @return pointer to table header, or NULL if not found
43  */
44 struct acpi_table_header *find_table(const char *sig)
45 {
46         struct acpi_rsdp *rsdp;
47         struct acpi_rsdt *rsdt;
48         int len, i, count;
49
50         rsdp = map_sysmem(gd->arch.acpi_start, 0);
51         if (!rsdp)
52                 return NULL;
53         rsdt = map_sysmem(rsdp->rsdt_address, 0);
54         len = rsdt->header.length - sizeof(rsdt->header);
55         count = len / sizeof(u32);
56         for (i = 0; i < count; i++) {
57                 struct acpi_table_header *hdr;
58
59                 hdr = map_sysmem(rsdt->entry[i], 0);
60                 if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN))
61                         return hdr;
62                 if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) {
63                         struct acpi_fadt *fadt = (struct acpi_fadt *)hdr;
64
65                         if (!memcmp(sig, "DSDT", ACPI_NAME_LEN) && fadt->dsdt)
66                                 return map_sysmem(fadt->dsdt, 0);
67                         if (!memcmp(sig, "FACS", ACPI_NAME_LEN) &&
68                             fadt->firmware_ctrl)
69                                 return map_sysmem(fadt->firmware_ctrl, 0);
70                 }
71         }
72
73         return NULL;
74 }
75
76 static int dump_table_name(const char *sig)
77 {
78         struct acpi_table_header *hdr;
79
80         hdr = find_table(sig);
81         if (!hdr)
82                 return -ENOENT;
83         printf("%.*s @ %08lx\n", ACPI_NAME_LEN, hdr->signature,
84                (ulong)map_to_sysmem(hdr));
85         print_buffer(0, hdr, 1, hdr->length, 0);
86
87         return 0;
88 }
89
90 static void list_fadt(struct acpi_fadt *fadt)
91 {
92         if (fadt->dsdt)
93                 dump_hdr(map_sysmem(fadt->dsdt, 0));
94         if (fadt->firmware_ctrl)
95                 dump_hdr(map_sysmem(fadt->firmware_ctrl, 0));
96 }
97
98 static int list_rsdt(struct acpi_rsdt *rsdt, struct acpi_xsdt *xsdt)
99 {
100         int len, i, count;
101
102         dump_hdr(&rsdt->header);
103         if (xsdt)
104                 dump_hdr(&xsdt->header);
105         len = rsdt->header.length - sizeof(rsdt->header);
106         count = len / sizeof(u32);
107         for (i = 0; i < count; i++) {
108                 struct acpi_table_header *hdr;
109
110                 if (!rsdt->entry[i])
111                         break;
112                 hdr = map_sysmem(rsdt->entry[i], 0);
113                 dump_hdr(hdr);
114                 if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN))
115                         list_fadt((struct acpi_fadt *)hdr);
116                 if (xsdt) {
117                         if (xsdt->entry[i] != rsdt->entry[i]) {
118                                 printf("   (xsdt mismatch %llx)\n",
119                                        xsdt->entry[i]);
120                         }
121                 }
122         }
123
124         return 0;
125 }
126
127 static int list_rsdp(struct acpi_rsdp *rsdp)
128 {
129         struct acpi_rsdt *rsdt;
130         struct acpi_xsdt *xsdt;
131
132         printf("RSDP %08lx %06x (v%02d %.6s)\n", (ulong)map_to_sysmem(rsdp),
133                rsdp->length, rsdp->revision, rsdp->oem_id);
134         rsdt = map_sysmem(rsdp->rsdt_address, 0);
135         xsdt = map_sysmem(rsdp->xsdt_address, 0);
136         list_rsdt(rsdt, xsdt);
137
138         return 0;
139 }
140
141 static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc,
142                         char *const argv[])
143 {
144         struct acpi_rsdp *rsdp;
145
146         rsdp = map_sysmem(gd->arch.acpi_start, 0);
147         if (!rsdp) {
148                 printf("No ACPI tables present\n");
149                 return 0;
150         }
151         printf("ACPI tables start at %lx\n", gd->arch.acpi_start);
152         list_rsdp(rsdp);
153
154         return 0;
155 }
156
157 static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc,
158                          char *const argv[])
159 {
160         bool dump_contents;
161
162         dump_contents = argc >= 2 && !strcmp("-d", argv[1]);
163         acpi_dump_items(dump_contents ? ACPI_DUMP_CONTENTS : ACPI_DUMP_LIST);
164
165         return 0;
166 }
167
168 static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
169                         char *const argv[])
170 {
171         const char *name;
172         char sig[ACPI_NAME_LEN];
173         int ret;
174
175         name = argv[1];
176         if (strlen(name) != ACPI_NAME_LEN) {
177                 printf("Table name '%s' must be four characters\n", name);
178                 return CMD_RET_FAILURE;
179         }
180         str_to_upper(name, sig, -1);
181         ret = dump_table_name(sig);
182         if (ret) {
183                 printf("Table '%.*s' not found\n", ACPI_NAME_LEN, sig);
184                 return CMD_RET_FAILURE;
185         }
186
187         return 0;
188 }
189
190 #ifdef CONFIG_SYS_LONGHELP
191 static char acpi_help_text[] =
192         "list - list ACPI tables\n"
193         "acpi items [-d]  - List/dump each piece of ACPI data from devices\n"
194         "acpi dump <name> - Dump ACPI table";
195 #endif
196
197 U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
198         U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
199         U_BOOT_SUBCMD_MKENT(items, 2, 1, do_acpi_items),
200         U_BOOT_SUBCMD_MKENT(dump, 2, 1, do_acpi_dump));