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 "printer.h"
14
15#ifdef CONFIG_LIB_SEL4_ACPI_DEBUG
16
17/************************
18 **** Debug features ****
19 ************************/
20#include <acpi/acpi.h>
21#include "acpi.h"
22
23#include <stdio.h>
24#include <string.h>
25
26static char
27pprint(char c)
28{
29    if (c < 0x32) {
30        return '.';
31    }
32    if (c < 0x7F) {
33        return c;
34    }
35    return '.';
36}
37
38void
39colour_bf(int i, const char* ptr)
40{
41    if (i == 3 && ((*ptr) & 0xff) == 0xbf) {
42        printf("\033[01;31m");
43    }
44}
45
46void
47colour_1a(int i, const char* ptr)
48{
49    (void)i;
50    if (((*ptr) & 0xff) == 0x1a) {
51        printf("\033[01;29m");
52    }
53}
54
55void
56colour_1d(int i, const char* ptr)
57{
58    (void)i;
59    if (((*ptr) & 0xff) == 0x1d) {
60        printf("\033[01;28m");
61    }
62}
63
64static void
65colour(int i, const char* ptr)
66{
67    colour_bf(i, ptr);
68    colour_1a(i, ptr);
69    colour_1d(i, ptr);
70}
71
72// print the raw table with "indent" printed before each column
73void
74acpi_print_table_raw(const void* start, int length)
75{
76    int i, j;
77    const char *ptr = start;
78    const char *end = start + length;
79
80    while (1) {
81        // store pointer to start of row for txt printing later
82        const char* row_start = ptr;
83
84        // Col1 : position
85        printf("0x%p: ", row_start);
86        // print hex values
87        for (i =  0; i < 4; i++) {
88            for (j = 0; j < 4; j++) {
89                if (ptr == end) {
90                    printf("   ");
91                } else {
92                    colour(j, ptr);
93                    printf("%02x ", (*ptr++) & 0xff);
94                    printf("\033[00m");
95                }
96            }
97            printf("  ");
98        }
99        // print txt
100        ptr = row_start;
101        for (i =  0; i < 4; i++) {
102            for (j = 0; j < 4; j++) {
103                printf("%c", pprint(*ptr++));
104                if (ptr == end) {
105                    printf("\n");
106                    return;
107                }
108            }
109            printf(" ");
110        }
111        printf("\n");
112    }
113}
114
115static void
116print_path(acpi_dmar_dscope_t* dscope)
117{
118    int entries = acpi_dmar_dscope_path_length(dscope);
119    acpi_device_path_t* path = acpi_dmar_path_first(dscope);
120    printf("\t\t<<<Path>>>\n");
121    while (entries-- > 0) {
122        printf("\t\tPCI device number = 0x%02x, ", path->device & 0xff);
123        printf("PCI function number = 0x%02x\n", path->function & 0xff);
124        path++;
125    }
126}
127
128static void
129print_dscope(acpi_dmar_remap_hdr_t* head, acpi_dmar_dscope_t* dscope)
130{
131    while (dscope != NULL) {
132        printf("\t<<Device Scope>>\n\t");
133        switch (dscope->type) {
134        case ACPI_DSCOPE_PCI_ENDPOINT:
135            printf("PCI Endpoint Device\n");
136            break;
137        case ACPI_DSCOPE_PCI_BRIDGE:
138            printf("PCI Sub-heirarchy\n");
139            break;
140        case ACPI_DSCOPE_IOAPIC:
141            printf("IOAPIC 0x%02x\n", dscope->enum_id & 0xff);
142            break;
143        case ACPI_DSCOPE_HPET:
144            printf("HPET timer 0x%02d\n", dscope->enum_id & 0xff);
145            break;
146        default:
147            printf("Unknown device scope\n");
148            acpi_print_table_raw(dscope, dscope->length);
149        }
150
151        if (ACPI_DSCOPE_VALID(dscope->type)) {
152            printf("\tStart bus number 0x%02x\n",
153                   dscope->start_bus_number & 0xff);
154        }
155
156        print_path(dscope);
157
158        dscope = acpi_dmar_next_dscope(head, dscope);
159    }
160}
161
162static void
163print_dmar(acpi_dmar_hdr_t* dmar)
164{
165    acpi_print_table_raw(dmar, dmar->header.length);
166
167    acpi_dmar_remap_hdr_t* sub = acpi_dmar_first_remap(dmar);
168    while (sub != NULL) {
169        switch (sub->type) {
170        case ACPI_DMAR_DRHD_TYPE:
171            printf("\n<DMA Remapping Hardware Unit Definition>\n");
172            acpi_dmar_drhd_t* drhd = (acpi_dmar_drhd_t*)sub;
173            printf("Flags 0x%02x\n", drhd->flags & 0xff);
174            printf("Segment number 0x%04x\n",
175                   drhd->segment_number & 0xffff);
176            printf("Base address 0x%016lx\n",
177                   (unsigned long)drhd->register_address);
178//            acpi_print_table_raw(drhd, drhd->header.length, "");
179            print_dscope(sub, acpi_dmar_drhd_first_dscope(drhd));
180            break;
181        case ACPI_DMAR_RMRR_TYPE:
182            printf("\n<Reserved Memory Region Reporting>\n");
183            acpi_dmar_rmrr_t* rmrr = (acpi_dmar_rmrr_t*)sub;
184            printf("Segment number 0x%04x\n",
185                   rmrr->segment_number & 0xffff);
186            printf("Memory range 0x%016lx -> 0x%016lx\n",
187                   (unsigned long)rmrr->base_address,
188                   (unsigned long)rmrr->limit_address);
189//            acpi_print_table_raw(rmrr, rmrr->header.length, "");
190            print_dscope(sub, acpi_dmar_rmrr_first_dscope(rmrr));
191            break;
192        case ACPI_DMAR_ATSR_TYPE:
193            printf("\n<root port ATS capbility Reporting>\n");
194            acpi_dmar_atsr_t* atsr = (acpi_dmar_atsr_t*)sub;
195            printf("Flags 0x%02x\n", atsr->flags & 0xff);
196            printf("Segment number 0x%04x\n",
197                   atsr->segment_number & 0xffff);
198//            acpi_print_table_raw(atsr, atsr->header.length, "");
199            print_dscope(sub, acpi_dmar_atsr_first_dscope(atsr));
200            break;
201        case ACPI_DMAR_RHSA_TYPE:
202            printf("\n<Remapping Hardware Affinity>\n");
203            acpi_dmar_rhsa_t* rhsa = (acpi_dmar_rhsa_t*)sub;
204            printf("Base address 0x%016lx\n",
205                   (unsigned long)rhsa->base_address);
206            printf("Proximity domain 0x%08x\n",
207                   rhsa->proximity_domain);
208//            acpi_print_table_raw(rhsa, sizeof(*rhsa), "");
209            break;
210        default:
211            printf("\n<Unknown remapping structure>\n");
212            acpi_print_table_raw(sub, sizeof(*sub));
213            break;
214        }
215        sub = acpi_dmar_next_remap(dmar, sub);
216    }
217}
218
219static void
220print_mcfg_desc(acpi_mcfg_desc_t* mcfg_desc)
221{
222    printf("<PCI Device Description %p>\n", mcfg_desc);
223    printf("Address: 0x%016lx\n", (unsigned long)mcfg_desc->address);
224    printf("Segment 0x%04x\n", mcfg_desc->segment);
225    printf("Bus 0x%02x - 0x%02x\n", mcfg_desc->bus_end,
226           mcfg_desc->bus_start);
227}
228
229static void
230print_mcfg(acpi_mcfg_t* mcfg)
231{
232    acpi_print_table_raw(mcfg, mcfg->header.length);
233    acpi_mcfg_desc_t* cur = acpi_mcfg_desc_first(mcfg);
234    while (cur != NULL) {
235        print_mcfg_desc(cur);
236        cur = acpi_mcfg_desc_next(mcfg, cur);
237    }
238}
239
240static void
241print_rsdt(acpi_rsdt_t* rsdt)
242{
243    acpi_print_table_raw(rsdt, rsdt->header.length);
244    printf("Child tables:\n");
245    uint32_t* next = acpi_rsdt_first(rsdt);
246    int entries = acpi_rsdt_entry_count(rsdt);
247    int i = 0;
248    while (next != NULL) {
249        printf("%d/%d -> %p\n", i++, entries, (void*)*next);
250        next = acpi_rsdt_next(rsdt, next);
251    }
252    printf("\n");
253}
254
255static void
256print_xsdt(acpi_xsdt_t* xsdt)
257{
258    acpi_print_table_raw(xsdt, xsdt->header.length);
259    printf("Child tables:\n");
260    uint64_t* next = acpi_xsdt_first(xsdt);
261    int entries = acpi_xsdt_entry_count(xsdt);
262    int i = 0;
263    while (next != NULL) {
264        printf("%d/%d -> %p\n", i++, entries,
265               (void*)(uintptr_t)*next);
266        next = acpi_xsdt_next(xsdt, next);
267    }
268    printf("\n");
269}
270
271static void
272print_rsdp(acpi_rsdp_t* rsdp)
273{
274    acpi_print_table_raw(rsdp, rsdp->length);
275    printf("RSDT->%p\n", (void*)rsdp->rsdt_address);
276    printf("XSDT->%p\n", (void*)(uintptr_t)rsdp->xsdt_address);
277    printf("\n");
278}
279
280static void
281print_madt(acpi_madt_t* madt)
282{
283    acpi_print_table_raw(madt, madt->header.length);
284    acpi_madt_ics_hdr_t* entry = acpi_madt_first_ics(madt);
285    while (entry != NULL) {
286        char* txt;
287        switch (entry->type) {
288        case ACPI_APIC_LOCAL:
289            txt = "LOCAL";
290            break;
291        case ACPI_APIC_ISO:
292            txt = "ISO";
293            break;
294        case ACPI_APIC_NMI:
295            txt = "NMI";
296            break;
297        case ACPI_APIC_LOCAL_NMI:
298            txt = "LOCAL NMI";
299            break;
300        case ACPI_APIC_LOCAL_AO:
301            txt = "LOCAL AO";
302            break;
303        case ACPI_APIC_SAPIC:
304            txt = "SAPIC";
305            break;
306        case ACPI_APIC_PINT_SRC:
307            txt = "PINT SRC";
308            break;
309        case ACPI_APIC_LOCAL_X2APIC:
310            txt = "LOCAL X2APIC";
311            break;
312        case ACPI_APIC_LOCAL_X2APIC_NMI:
313            txt = "LOCAL X2APIC_NMI";
314            break;
315        case ACPI_APIC_GIC:
316            txt = "GIC";
317            break;
318        case ACPI_APIC_GICD:
319            txt = "GICD";
320            break;
321        case ACPI_APIC_IOSAPIC:
322            txt = "IOSAPIC";
323            break;
324        case ACPI_APIC_IOAPIC:
325            txt = "IOAPIC";
326            break;
327        default:
328            txt = "Unknown";
329            break;
330        }
331        printf("<<%s>>\n", txt);
332        acpi_print_table_raw(entry, entry->length);
333        entry = acpi_madt_next_ics(madt, entry);
334    }
335}
336
337void
338acpi_print_table(const void* start)
339{
340    // for now, just find the length of the table and print
341    // in raw format
342    int len = acpi_table_length(start);
343    if (len > 0) {
344        if (ACPI_TABLE_TEST(start, DMAR)) {
345            print_dmar((acpi_dmar_hdr_t*)start);
346        } else if (ACPI_TABLE_TEST(start, MCFG)) {
347            print_mcfg((acpi_mcfg_t*)start);
348        } else if (ACPI_TABLE_TEST(start, RSDT)) {
349            print_rsdt((acpi_rsdt_t*)start);
350        } else if (ACPI_TABLE_TEST(start, XSDT)) {
351            print_xsdt((acpi_xsdt_t*)start);
352        } else if (ACPI_TABLE_TEST(start, RSDP)) {
353            print_rsdp((acpi_rsdp_t*)start);
354        } else if (ACPI_TABLE_TEST(start, MADT)) {
355            print_madt((acpi_madt_t*)start);
356        } else {
357            acpi_print_table_raw(start, len);
358        }
359    }
360}
361
362void
363acpi_print_regions(const RegionList_t* rl)
364{
365    printf("\n");
366    printf("index | Signiture  | Address                | "
367           "Adjusted address       | parent index\n");
368    int i;
369    for (i = 0; i < 83; i++) {
370        printf("-");
371    }
372    printf("\n");
373
374    for (i = 0; i < rl->region_count; i++) {
375        const Region_t* r = rl->regions + i;
376        const char* sig = acpi_sig_str(r->type);
377        int sig_len = strlen(sig);
378        printf("  %2d  | ", i);
379        printf("\"%s\"",  acpi_sig_str(r->type));
380        while (sig_len++ < 9) {
381            printf(" ");
382        }
383        printf("| ");
384
385        printf("%p->%p | ", r->start, r->start + r->size);
386        printf("%p->", r->start - rl->offset);
387        printf("%p | ", r->start + r->size - rl->offset);
388        printf("%3d\n", r->parent);
389    }
390}
391
392#endif
393