Merge tag 'efi-2022-07-rc2' of https://source.denx.de/u-boot/custodians/u-boot-efi
[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  %5x", 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_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  %5x  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_acpi_start(), 0);
147         if (!rsdp) {
148                 printf("No ACPI tables present\n");
149                 return 0;
150         }
151         printf("Name      Base   Size  Detail\n");
152         printf("----  --------  -----  ------\n");
153         list_rsdp(rsdp);
154
155         return 0;
156 }
157
158 static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc,
159                          char *const argv[])
160 {
161         bool dump_contents;
162
163         dump_contents = argc >= 2 && !strcmp("-d", argv[1]);
164         acpi_dump_items(dump_contents ? ACPI_DUMP_CONTENTS : ACPI_DUMP_LIST);
165
166         return 0;
167 }
168
169 static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
170                         char *const argv[])
171 {
172         const char *name;
173         char sig[ACPI_NAME_LEN];
174         int ret;
175
176         name = argv[1];
177         if (strlen(name) != ACPI_NAME_LEN) {
178                 printf("Table name '%s' must be four characters\n", name);
179                 return CMD_RET_FAILURE;
180         }
181         str_to_upper(name, sig, ACPI_NAME_LEN);
182         ret = dump_table_name(sig);
183         if (ret) {
184                 printf("Table '%.*s' not found\n", ACPI_NAME_LEN, sig);
185                 return CMD_RET_FAILURE;
186         }
187
188         return 0;
189 }
190
191 #ifdef CONFIG_SYS_LONGHELP
192 static char acpi_help_text[] =
193         "list - list ACPI tables\n"
194         "acpi items [-d]  - List/dump each piece of ACPI data from devices\n"
195         "acpi dump <name> - Dump ACPI table";
196 #endif
197
198 U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
199         U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
200         U_BOOT_SUBCMD_MKENT(items, 2, 1, do_acpi_items),
201         U_BOOT_SUBCMD_MKENT(dump, 2, 1, do_acpi_dump));