1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#include "browser.h"
14
15#ifdef CONFIG_LIB_SEL4_ACPI_DEBUG
16
17#include "acpi.h"
18#include "regions.h"
19#include "printer.h"
20
21#include <stdio.h>
22#include <string.h>
23
24static int
25_browse_tables(void* table, size_t offset)
26{
27    /*
28     * NOTE: offset added to address JUST BEFORE moving
29     * to the next table
30     */
31    void* vector[26] = {NULL};
32
33    printf("reading table at %p\n", table);
34
35    do {
36
37        // print table and set links
38        printf("\n");
39        region_type_t table_type = acpi_sig_id(table);
40        char input;
41
42        switch (table_type) {
43        case ACPI_RSDP: {
44            printf("Root System Descriptor table Pointer\n");
45            acpi_print_table(table);
46            acpi_rsdp_t* rsdp = (acpi_rsdp_t*)table;
47            vector[0] = (void*)rsdp->rsdt_address;
48            vector[1] = (void*)(uintptr_t)rsdp->xsdt_address;
49            printf("\n");
50            printf("a - RSDT at %p\n", vector[0]);
51            printf("b - XSDT at %p\n", vector[1]);
52            break;
53        }
54        case ACPI_RSDT: {
55            printf("Root System Descriptor Table\n");
56            acpi_print_table(table);
57            acpi_rsdt_t* rsdt = (acpi_rsdt_t*)table;
58            printf("\n");
59            int i = 0;
60            uint32_t* entry = acpi_rsdt_first(rsdt);
61            while (entry != NULL) {
62                char sig[5];
63                sig[4] = '\0';
64                memcpy(sig, (char*)(*entry) + offset, 4);
65                vector[i] = (void*)(*entry);
66                printf("%c - %s table at %p\n", i + 'a', sig, vector[i]);
67                i++;
68                entry = acpi_rsdt_next(rsdt, entry);
69            }
70            break;
71        }
72        case ACPI_XSDT: {
73            printf("eXtended root System Descriptor Table\n");
74            acpi_print_table(table);
75            acpi_xsdt_t* xsdt = (acpi_xsdt_t*)table;
76            printf("\n");
77            int i = 0;
78            uint64_t* entry = acpi_xsdt_first(xsdt);
79            while (entry != NULL) {
80                char sig[5];
81                sig[4] = '\0';
82                char* _e = (char*)(uintptr_t)(*entry);
83                memcpy(sig, _e, 4);
84                vector[i] = _e;
85                printf("%c - %s table at %p\n", i + 'a', sig, vector[i]);
86                i++;
87                entry = acpi_xsdt_next(xsdt, entry);
88            }
89            break;
90        }
91        case ACPI_FADT: {
92            printf("Fixed ACPI Description Table\n");
93            acpi_print_table(table);
94            acpi_fadt_t* fadt = (acpi_fadt_t*)table;
95            vector[0] = (void*)fadt->facs_address;
96            vector[1] = (void*)fadt->dsdt_address;
97            vector[2] = (void*)(uintptr_t)fadt->x_facs_address;
98            vector[3] = (void*)(uintptr_t)fadt->x_dsdt_address;
99            printf("\n");
100            printf("a -  FACS at %p\n", vector[0]);
101            printf("b -  DSDT at %p\n", vector[1]);
102            printf("c - XFACS at %p\n", vector[2]);
103            printf("d - XDSDT at %p\n", vector[3]);
104            break;
105        }
106        case ACPI_FACS: {
107            printf("Firmware ACPI Constrol Structure\n");
108            acpi_print_table(table);
109            acpi_facs_t* facs = (acpi_facs_t*)table;
110            vector[0] = (void*)facs->firmware_walking_vector;
111            vector[3] = (void*)(uintptr_t)facs->x_firmware_walking_vector;
112            printf("\n");
113            printf("a - Firware Walking vector at %p\n", vector[0]);
114            printf("b - X Firware walking vector at %p\n", vector[1]);
115            break;
116        }
117        case ACPI_MCFG:
118            printf("PCI Memory mapped ConFiGuration\n");
119            acpi_print_table(table);
120            break;
121        case ACPI_DSDT:
122            printf("Differentiated System Description Table\n");
123            acpi_print_table(table);
124            break;
125        case ACPI_SSDT:
126            printf("Secondary System Description Table\n");
127            acpi_print_table(table);
128            break;
129        case ACPI_SPMI:
130            printf("Server Platform Management Interface table\n");
131            acpi_print_table(table);
132            break;
133        case ACPI_HPET:
134            printf("High Precision Event Timer table\n");
135            acpi_print_table(table);
136            break;
137        case ACPI_SPCR:
138            printf("Serial Port Console Redirection table\n");
139            acpi_print_table(table);
140            break;
141        case ACPI_BOOT:
142            printf("Boot flags table\n");
143            acpi_print_table(table);
144            break;
145        case ACPI_DMAR:
146            printf("DMA Remapping table\n");
147            acpi_print_table(table);
148            break;
149        case ACPI_ASF :
150            printf("Alert Standard Format table\n");
151            acpi_print_table(table);
152            break;
153        case ACPI_HEST:
154            printf("Hardware Error Source Table\n");
155            acpi_print_table(table);
156            break;
157        case ACPI_ERST:
158            printf("Error Record Serialisation Table\n");
159            acpi_print_table(table);
160            break;
161        case ACPI_BERT:
162            printf("Boot Error Record Table\n");
163            acpi_print_table(table);
164            break;
165        case ACPI_EINJ:
166            printf("Error INjection Table\n");
167            acpi_print_table(table);
168            break;
169        case ACPI_MADT:
170            printf("Multiple Apic Descriptor table\n");
171            acpi_print_table(table);
172            break;
173        case ACPI_ASPT:
174            printf("ASPT -- Unknown table\n");
175            acpi_print_table(table);
176            break;
177
178        default:
179            printf("Unknown Table\n");
180            acpi_print_table(table);
181        }
182
183        // collect input and act
184        do {
185            printf(">>");
186            input = getchar();
187
188            if (input >= 'a' && input <= 'z') {
189                // input steps into another table
190                if (vector[input - 'a'] != NULL) {
191                    void* next_tbl;
192                    next_tbl = vector[input - 'a'] + offset;
193                    if (_browse_tables(next_tbl, offset)) {
194                        return 1 /* quit */;
195                    } else {
196                        input = 'p';
197                    }
198                }
199            }
200            // other options
201            switch (input) {
202            case 'p':
203                break;
204            case 'q':
205                return 1;
206            case '\\':
207                return 0;
208            case '?':
209            default:
210                printf("\n"
211                       "p - print table\n"
212                       "q - quit\n"
213                       "\\ - go up 1 table level\n"
214                       "[a-z] Traverse tables\n");
215                break;
216            }
217        } while (input != 'p');
218    } while (1);
219}
220
221void
222acpi_browse_tables(const acpi_rsdp_t* rsdp, size_t offset)
223{
224    _browse_tables((void*)rsdp, offset);
225}
226
227static int
228_browse_regions(const RegionList_t* rlist, int parent)
229{
230    /*
231     * NOTE: We don't use offsets here because we are following
232     * the absolute address listed in the region list instead of
233     * the link addresses contained within the tables.
234     */
235
236    while (1) {
237        /* print table at region "parent" */
238        if (parent != NOPARENT) {
239            acpi_print_table(rlist->regions[parent].start);
240        } else {
241            printf("Root tables\n");
242        }
243
244        /* print children */
245        int children[MAX_REGIONS];
246        int child_count = 0;
247        int i;
248        for (i = 0; i < rlist->region_count; i++) {
249            const Region_t* r = rlist->regions + i;
250            if (r->parent == parent) {
251                const char* sig = acpi_sig_str(r->type);
252                char key = child_count + 'a';
253                printf("%c - %s at %p\n", key, sig, r->start);
254                children[child_count++] = i;
255            }
256        }
257
258        do {
259            printf(">>");
260            char input = getchar();
261            printf("%c\n\n", input);
262
263            unsigned char key = input - 'a';
264            if (key < child_count) {
265                // input steps into another table
266                if (_browse_regions(rlist, children[key])) {
267                    return 1 /* quit */;
268                } else {
269                    break; /* restart loop, print tables */
270                }
271            }
272
273            // other options
274            switch (input) {
275            case 'p':
276                break; /* restart loop, print tables */
277            case 'q':
278                return 1; /* exit */
279            case '\\':
280                return 0; /* up one level */
281            case '?':
282            default:
283                printf("\n"
284                       "p - print table\n"
285                       "q - quit\n"
286                       "\\ - go up 1 table level\n"
287                       "[a-%c] Traverse tables\n",
288                       'a' + child_count);
289                break;
290            }
291        } while (1);
292    }
293    while (1);
294}
295
296void
297acpi_browse_regions(const RegionList_t* rlist)
298{
299    _browse_regions(rlist, NOPARENT);
300}
301
302#endif
303