1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 2009-2011 Erwan Velu - All Rights Reserved
4 *
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
12 * conditions:
13 *
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * -----------------------------------------------------------------------
27 */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <memory.h>
32 #include <dprintf.h>
33 #include <stdlib.h>
34 #include "acpi/acpi.h"
35
36 /* Parse the apic structures */
add_apic_structure(s_acpi * acpi,uint8_t * q)37 static uint8_t *add_apic_structure(s_acpi * acpi, uint8_t * q)
38 {
39 uint8_t type = *q;
40 q++;
41 uint8_t length = *q;
42 q++;
43 s_processor_local_apic *sla;
44 s_io_apic *sio;
45 s_interrupt_source_override *siso;
46 s_nmi *snmi;
47 s_local_apic_nmi *slan;
48 s_local_apic_address_override *slaao;
49 s_io_sapic *siosapic;
50 s_local_sapic *sls;
51 s_madt *madt = &acpi->madt;
52
53 switch (type) {
54 case PROCESSOR_LOCAL_APIC:
55 sla = &madt->processor_local_apic[madt->processor_local_apic_count];
56 sla->type = type;
57 sla->length = length;
58 cp_struct(&sla->acpi_id);
59 cp_struct(&sla->apic_id);
60 cp_struct(&sla->flags);
61 madt->processor_local_apic_count++;
62 break;
63 case IO_APIC:
64 sio = &madt->io_apic[madt->io_apic_count];
65 sio->type = type;
66 sio->length = length;
67 cp_struct(&sio->io_apic_id);
68 cp_struct(&sio->reserved);
69 cp_struct(&sio->io_apic_address);
70 cp_struct(&sio->global_system_interrupt_base);
71 madt->io_apic_count++;
72 break;
73 case INTERRUPT_SOURCE_OVERRIDE:
74 siso =
75 &madt->interrupt_source_override[madt->
76 interrupt_source_override_count];
77 siso->type = type;
78 siso->length = length;
79 siso->bus = *q;
80 q++;
81 siso->source = *q;
82 q++;
83 cp_struct(&siso->global_system_interrupt);
84 cp_struct(&siso->flags);
85 madt->interrupt_source_override_count++;
86 break;
87 case NMI:
88 snmi = &madt->nmi[madt->nmi_count];
89 snmi->type = type;
90 snmi->length = length;
91 cp_struct(&snmi->flags);
92 cp_struct(&snmi->global_system_interrupt);
93 madt->nmi_count++;
94 break;
95 case LOCAL_APIC_NMI_STRUCTURE:
96 slan = &madt->local_apic_nmi[madt->local_apic_nmi_count];
97 slan->type = type;
98 slan->length = length;
99 cp_struct(&slan->acpi_processor_id);
100 cp_struct(&slan->flags);
101 cp_struct(&slan->local_apic_lint);
102 madt->local_apic_nmi_count++;
103 break;
104 case LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE:
105 slaao =
106 &madt->local_apic_address_override[madt->
107 local_apic_address_override_count];
108 slaao->type = type;
109 slaao->length = length;
110 cp_struct(&slaao->reserved);
111 cp_struct(&slaao->local_apic_address);
112 madt->local_apic_address_override_count++;
113 break;
114 case IO_SAPIC:
115 siosapic = &madt->io_sapic[madt->io_sapic_count];
116 siosapic->type = type;
117 siosapic->length = length;
118 cp_struct(&siosapic->io_apic_id);
119 cp_struct(&siosapic->reserved);
120 cp_struct(&siosapic->global_system_interrupt_base);
121 cp_struct(&siosapic->io_sapic_address);
122 madt->io_sapic_count++;
123 break;
124 case LOCAL_SAPIC:
125 sls = &madt->local_sapic[madt->local_sapic_count];
126 sls->type = type;
127 sls->length = length;
128 cp_struct(&sls->acpi_processor_id);
129 cp_struct(&sls->local_sapic_id);
130 cp_struct(&sls->local_sapic_eid);
131 cp_struct(sls->reserved);
132 cp_struct(&sls->flags);
133 cp_struct(&sls->acpi_processor_uid_value);
134 if ((sls->acpi_processor_uid_string =
135 malloc(length - ACPI_PROCESSOR_UID_STRING_OFFSET)) != NULL) {
136 memcpy(sls->acpi_processor_uid_string, q,
137 length - ACPI_PROCESSOR_UID_STRING_OFFSET);
138 q += length - ACPI_PROCESSOR_UID_STRING_OFFSET;
139 }
140 madt->local_sapic_count++;
141 break;
142 default:
143 printf("Unkown APIC structure type %u, size=%u \n", type, length);
144 q += length - 2;
145 break;
146 }
147 return q;
148 }
149
parse_madt(s_acpi * acpi)150 void parse_madt(s_acpi * acpi)
151 {
152 /* Let's seach for FADT table */
153 uint8_t *q, *max_address;
154 s_madt *m = &acpi->madt;
155
156 /* Fixing table name */
157 memcpy(m->header.signature, APIC, sizeof(APIC));
158
159 /* Copying remaining structs */
160 q = (uint8_t *)m->address;
161 q += ACPI_HEADER_SIZE;
162
163 max_address = (uint8_t *)m->address;
164 max_address += m->header.length;
165
166 cp_struct(&m->local_apic_address);
167 cp_struct(&m->flags);
168
169 while (q < max_address) {
170 q = add_apic_structure(acpi, q);
171 }
172 }
173